Decompiled source of Hunters Instinct v1.0.2

plugins/HuntersInstinct.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using 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: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyFileVersion("1.0.2")]
[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 tracking 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: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: <4ea261ca-605e-41b0-8350-3d99fb76a15e>RefSafetyRules(11)]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<dc7e7395-3cfb-4ae6-b5f9-41196f971326>Embedded]
	internal sealed class <dc7e7395-3cfb-4ae6-b5f9-41196f971326>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[<dc7e7395-3cfb-4ae6-b5f9-41196f971326>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class <f280da0b-cf6f-4ac1-bf8c-0c34672954c6>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <f280da0b-cf6f-4ac1-bf8c-0c34672954c6>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <f280da0b-cf6f-4ac1-bf8c-0c34672954c6>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[<dc7e7395-3cfb-4ae6-b5f9-41196f971326>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class <f31aece1-10b3-45b1-b44f-172fd99b28e9>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <f31aece1-10b3-45b1-b44f-172fd99b28e9>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[<dc7e7395-3cfb-4ae6-b5f9-41196f971326>Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	internal sealed class <4ea261ca-605e-41b0-8350-3d99fb76a15e>RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public <4ea261ca-605e-41b0-8350-3d99fb76a15e>RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HuntersInstinct
{
	public sealed class HuntersInstinctActivation
	{
		public struct Result
		{
			public bool Active;

			public float StaminaCost;
		}

		private bool _releaseRequired;

		internal bool RequiresRelease => _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;
		}
	}
	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;
		}
	}
	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 FootprintStyle GetFootprintStyle(string prefab, string format)
		{
			return (format ?? "Auto").Trim().ToLowerInvariant() switch
			{
				"hooves" => new FootprintStyle(0, 0.32f), 
				"paws" => new FootprintStyle(1, 0.36f), 
				"bird" => new FootprintStyle(3, 0.22f), 
				"claws" => new FootprintStyle(2, 0.3f), 
				_ => GetFootprintStyle(prefab), 
			};
		}

		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 bool CanDetectPlayer(bool enabled, bool self, bool dead, float level, int minimumLevel, float distanceSquared, float range, bool onlyPvp, bool pvp)
		{
			if (!enabled || self || dead || level < (float)minimumLevel || (onlyPvp && !pvp))
			{
				return false;
			}
			if (float.IsNaN(distanceSquared) || float.IsInfinity(distanceSquared) || distanceSquared < 0f)
			{
				return false;
			}
			if (float.IsNaN(range) || float.IsInfinity(range))
			{
				return false;
			}
			range = Math.Max(1f, Math.Min(100f, range));
			return distanceSquared <= range * range;
		}

		public static bool ShouldSample(bool charging, bool hasActiveTrails)
		{
			return charging || hasActiveTrails;
		}

		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));
		}
	}
	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 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)));
		}
	}
	[BepInPlugin("radamanto.HuntersInstinct", "Hunter's Instinct", "1.0.2")]
	public sealed class HuntersInstinctPlugin : BaseUnityPlugin
	{
		private sealed class GroundMark
		{
			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 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 class ConfigurationManagerAttributes
		{
			public bool? Browsable = false;
		}

		[HarmonyPatch(typeof(Skills), "CheatRaiseSkill")]
		private static class Skills_CheatRaiseSkill_Tracking
		{
			private static bool Prefix(Skills __instance, string name, float value, bool showMessage)
			{
				if (!IsTrackingName(name))
				{
					return true;
				}
				RegisterSkill(__instance);
				Skill skill = __instance.GetSkill((SkillType)1978436211);
				skill.m_level = Mathf.Clamp(skill.m_level + value, 0f, 100f);
				if (__instance.m_useSkillCap)
				{
					__instance.RebalanceSkills((SkillType)1978436211);
				}
				if (showMessage && Object.op_Implicit((Object)(object)Console.instance))
				{
					Console.instance.Print("Tracking = " + skill.m_level);
				}
				return false;
			}
		}

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

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

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

		[HarmonyPatch(typeof(Skills), "IsSkillValid")]
		private static class Skills_IsSkillValid_AllowTracking
		{
			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;
				}
			}
		}

		private readonly List<GroundMark> _marks = new List<GroundMark>();

		private readonly Stack<GroundMark> _markPool = new Stack<GroundMark>();

		private string _cachedMarkColor;

		private Color _parsedMarkColor;

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

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

		private float _nextTrailResourceAttempt;

		private bool _trailResourceWarning;

		private Material _trailMaterial;

		private MaterialPropertyBlock _trailProperties;

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

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

		private ConfigEntry<string> _footprintStyle;

		private ConfigEntry<bool> _modEnabled;

		private ConfigEntry<bool> _trackTamed;

		private ConfigEntry<bool> _tamedExperience;

		private ConfigEntry<bool> _trailsEnabled;

		private ConfigEntry<bool> _instinctEnabled;

		private ConfigEntry<KeyCode> _activationKey;

		private ConfigEntry<string> _excludedPrefabs;

		private ConfigEntry<string> _markColor;

		private ConfigEntry<string> _instinctColor;

		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<bool> _playerTrackingEnabled;

		private ConfigEntry<bool> _onlyPvpPlayers;

		private ConfigEntry<int> _playerMinimumLevel;

		private ConfigEntry<float> _playerDetectionRange;

		private ConfigEntry<string> _playerAuraColor;

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

		internal const string ModId = "HuntersInstinct";

		internal const string ModVersion = "1.0.2";

		internal const string Author = "radamanto";

		internal const string ModGUID = "radamanto.HuntersInstinct";

		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 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 _trackingActive;

		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 readonly List<Character> _characterSnapshot = new List<Character>();

		[<f280da0b-cf6f-4ac1-bf8c-0c34672954c6>Nullable(2)]
		private static ConfigSync ConfigSync;

		[<f280da0b-cf6f-4ac1-bf8c-0c34672954c6>Nullable(2)]
		private static ConfigEntry<bool> _serverConfigLocked;

		[<f280da0b-cf6f-4ac1-bf8c-0c34672954c6>Nullable(2)]
		private FileSystemWatcher _configWatcher;

		private long _lastCfgWrite;

		private bool _reloadScheduled;

		private bool _watcherReady;

		private Texture2D _auraTexture;

		private Texture2D _pulseTexture;

		private string _cachedInstinctColor;

		private Color _parsedInstinctColor;

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

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

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

		private readonly HashSet<Character> _selectedInstinctTargets = new HashSet<Character>();

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

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

		private float _nextExperience;

		private Vector3 _trainingOrigin;

		private readonly HuntersInstinctExclusions _exclusions = new HuntersInstinctExclusions();

		private const float MaximumPlayerTrackingRange = 100f;

		private float _trackingLevel;

		private string _cachedPlayerAuraColor;

		private Color _parsedPlayerAuraColor;

		private float _nextEligibilityCheck;

		internal const int TrackingSkillId = 1978436211;

		internal const SkillType TrackingSkill = (SkillType)1978436211;

		private TMP_FontAsset _titleFont;

		private Material _titleMaterial;

		private TextMeshProUGUI _focusLabel;

		private float _nextFontSearch;

		private bool _verifiedTitleFont;

		private GameObject _focusCanvas;

		private int _focusScreenHeight;

		private bool _focusTextDirty = true;

		private bool InstinctActive => _trackingActive && (_instinctEnabled.Value || _playerTrackingEnabled.Value) && Object.op_Implicit((Object)(object)_activePlayer) && !((Character)_activePlayer).IsDead();

		private float PlayerTrackingReach => Mathf.Clamp(_playerDetectionRange.Value, 1f, 100f);

		private void RefreshMarkEligibility()
		{
			for (int num = _marks.Count - 1; num >= 0; num--)
			{
				if (!CanTrackMark(_marks[num]))
				{
					Recycle(_marks[num]);
					_marks.RemoveAt(num);
				}
			}
		}

		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();
				}
				GroundMark groundMark;
				if (_markPool.Count > 0)
				{
					groundMark = _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;
					groundMark = new GroundMark
					{
						Object = val2,
						Renderer = val3,
						Filter = filter
					};
				}
				groundMark.Born = now;
				groundMark.Lifetime = _trailLifetime;
				groundMark.Source = source;
				groundMark.Prefab = HuntersInstinctExclusions.PrefabName(((Object)((Component)source).gameObject).name);
				groundMark.WasTamed = source.IsTamed();
				groundMark.Studied = false;
				groundMark.Filter.sharedMesh = _footprintMeshes[style.Shape];
				groundMark.Object.transform.position = ((RaycastHit)(ref val)).point + ((RaycastHit)(ref val)).normal * 0.018f;
				groundMark.Object.transform.rotation = Quaternion.LookRotation(Vector3.ProjectOnPlane(direction, ((RaycastHit)(ref val)).normal), ((RaycastHit)(ref val)).normal);
				groundMark.Object.transform.localScale = Vector3.one * style.Size * 1f;
				groundMark.Object.SetActive(true);
				_marks.Add(groundMark);
			}
		}

		private void FadeTrails(float now)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			if (_cachedMarkColor != _markColor.Value)
			{
				_cachedMarkColor = _markColor.Value;
				if (!ColorUtility.TryParseHtmlString(_cachedMarkColor, ref _parsedMarkColor))
				{
					_parsedMarkColor = new Color(1f, 0.125f, 0.125f);
				}
			}
			Color parsedMarkColor = _parsedMarkColor;
			for (int num = _marks.Count - 1; num >= 0; num--)
			{
				GroundMark groundMark = _marks[num];
				float num2 = HuntersInstinctRules.Opacity(now - groundMark.Born, groundMark.Lifetime, 0.7f);
				if (num2 <= 0f || !_trailsEnabled.Value)
				{
					Recycle(groundMark);
					_marks.RemoveAt(num);
				}
				else
				{
					parsedMarkColor.a = HuntersInstinctRules.FootprintOpacity(now - groundMark.Born, groundMark.Lifetime, 0.7f, 0.25f);
					_trailProperties.SetColor(ColorId, parsedMarkColor);
					((Renderer)groundMark.Renderer).SetPropertyBlock(_trailProperties);
				}
			}
			while (_marks.Count > 1200)
			{
				RecycleOldest();
			}
		}

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

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

		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;
		}

		private void EnsureTrailResources(float now)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)_trailMaterial) || now < _nextTrailResourceAttempt)
			{
				return;
			}
			_nextTrailResourceAttempt = now + 5f;
			try
			{
				Shader val = Shader.Find("Sprites/Default");
				if (!Object.op_Implicit((Object)(object)val) || !val.isSupported)
				{
					throw new InvalidOperationException("Sprites/Default is unavailable or unsupported.");
				}
				_trailMaterial = new Material(val)
				{
					name = "HuntersInstinct.RedFootprints",
					renderQueue = 3000
				};
				if (!_trailMaterial.HasProperty(ColorId))
				{
					throw new InvalidOperationException("Footprint shader has no _Color property.");
				}
				_trailMaterial.mainTexture = (Texture)(object)Texture2D.whiteTexture;
				for (int i = 0; i < _footprintMeshes.Length; i++)
				{
					_footprintMeshes[i] = MakeFootprintMesh(i);
				}
				_trailProperties = new MaterialPropertyBlock();
				_trailResourceWarning = false;
			}
			catch (Exception ex)
			{
				DisposeTrailResources();
				if (!_trailResourceWarning)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Footprints unavailable; other tracking features remain active. Retrying during tracking: " + ex.Message));
				}
				_trailResourceWarning = true;
			}
		}

		private void DisposeTrailResources()
		{
			foreach (GroundMark item in _markPool)
			{
				if (Object.op_Implicit((Object)(object)item.Object))
				{
					Object.Destroy((Object)(object)item.Object);
				}
			}
			_markPool.Clear();
			for (int i = 0; i < _footprintMeshes.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)_footprintMeshes[i]))
				{
					Object.Destroy((Object)(object)_footprintMeshes[i]);
				}
				_footprintMeshes[i] = null;
			}
			if (Object.op_Implicit((Object)(object)_trailMaterial))
			{
				Object.Destroy((Object)(object)_trailMaterial);
			}
			_trailMaterial = null;
			_trailProperties = null;
		}

		private void SampleTrails(float now, List<Character> characters)
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: 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_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: 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_02d3: 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_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: 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_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			if (!_trailsEnabled.Value || !Object.op_Implicit((Object)(object)_trailMaterial))
			{
				ClearTrails();
				return;
			}
			Vector3 val3 = default(Vector3);
			foreach (Character character in characters)
			{
				if (!Object.op_Implicit((Object)(object)character))
				{
					continue;
				}
				HuntersInstinctRules.Kind kind = Classify(character);
				if (kind == HuntersInstinctRules.Kind.Ignore)
				{
					_trails.Remove(character);
					continue;
				}
				Vector3 position = ((Component)character).transform.position;
				BaseAI baseAI = character.GetBaseAI();
				if (!(baseAI is AnimalAI))
				{
					_trails.Remove(character);
					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 = _trackingActive && flag3;
				if (!_trails.TryGetValue(character, out var value))
				{
					if (!flag4)
					{
						continue;
					}
					value = new Trail
					{
						Previous = position,
						Seen = now,
						Style = HuntersInstinctRules.GetFootprintStyle(((Object)((Component)character).gameObject).name.Replace("(Clone)", "").Trim(), _footprintStyle.Value)
					};
					_trails.Add(character, value);
				}
				bool fleeing = baseAI is AnimalAI && baseAI.IsAlerted();
				if (!value.Tracking.Update(now, _trackingDuration, flag4, fleeing, flag3))
				{
					_trails.Remove(character);
					continue;
				}
				value.Seen = now;
				Vector3 val2 = position - value.Previous;
				((Vector3)(ref val3))..ctor(val2.x, 0f, val2.z);
				bool flag5 = !character.IsSwimming() && !character.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, character, 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 ClearTrails()
		{
			foreach (GroundMark mark in _marks)
			{
				Recycle(mark);
			}
			_marks.Clear();
			_trails.Clear();
		}

		private void Configure()
		{
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Expected O, but got Unknown
			//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Expected O, but got Unknown
			//IL_0515: Unknown result type (might be due to invalid IL or missing references)
			//IL_0520: Expected O, but got Unknown
			_modEnabled = BindConfig("01 - General", "01 - Enabled", value: true, "Enable tracking trails and tracking instinct.");
			_trackTamed = BindConfig("01 - General", "02 - Track Tamed Creatures", value: false, "Allow footprints and instinct marks for tamed creatures.");
			_activationKey = BindConfig<KeyCode>("01 - General", "03 - Activation Key", (KeyCode)308, "Hold this key to activate tracking mode. Release to stop.", synchronizedSetting: false);
			_tamedExperience = BindConfig("01 - General", "04 - Gain Experience From Tamed Creatures", value: false, "Allow tracking experience from tamed creatures. Requires Track Tamed Creatures.");
			_excludedPrefabs = BindConfig("01 - General", "05 - Excluded Prefabs", "", "Comma-separated exact prefab names excluded from tracking and tracking experience.");
			_crouchingMultiplier = Range("06 - Localization Movement", "01 - Crouching Time Multiplier", 1f, "Multiply localization time while crouching.", 0.1f, 10f);
			_walkingMultiplier = Range("06 - Localization Movement", "02 - Walking Time Multiplier", 2f, "Multiply localization time while walking or standing.", 0.1f, 10f);
			_runningMultiplier = Range("06 - Localization Movement", "03 - Running Time Multiplier", 4f, "Multiply localization time while running.", 0.1f, 10f);
			_featherFallMultiplier = Range("06 - Localization Movement", "04 - Feather Fall Time Multiplier", 4f, "Multiply localization time while descending with a fall-speed-limiting effect.", 0.1f, 10f);
			_trailsEnabled = BindConfig("02 - Footprints", "01 - Enabled", value: true, "Detect eligible AnimalAI creatures while tracking mode is active.");
			_markColor = BindConfig("02 - Footprints", "02 - Color", "#FF2020", "Footprint color in #RRGGBB format. Invalid values use red.", synchronizedSetting: false);
			_footprintStyle = BindConfig("02 - Footprints", "03 - Format", "Auto", new ConfigDescription("Footprint format. Auto uses the creature-specific shape.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[5] { "Auto", "Hooves", "Paws", "Bird", "Claws" }), Array.Empty<object>()), synchronizedSetting: false);
			_focusStart = Range("03 - Tracking Skill", "12 - Localization Time At Level 0", 2f, "Seconds to complete localization at level zero.", 0.1f, 30f);
			_focusEnd = Range("03 - Tracking Skill", "13 - Localization Time At Level 100", 0.5f, "Localization time at level 100.", 0.1f, 30f);
			_auraLifeStart = Range("03 - Tracking Skill", "14 - Instinct Mark Duration At Level 0", 5f, "Seconds an instinct mark remains at level zero.", 0.1f, 120f);
			_auraLifeEnd = Range("03 - Tracking Skill", "15 - Instinct Mark Duration At Level 100", 15f, "Instinct mark duration at level 100.", 0.1f, 120f);
			_trackingStart = Range("03 - Tracking Skill", "10 - Tracking Duration At Level 0", 15f, "Seconds a detected creature keeps generating footprints.", 1f, 120f);
			_trackingEnd = Range("03 - Tracking Skill", "11 - Tracking Duration At Level 100", 30f, "Tracking duration at level 100.", 1f, 120f);
			_trailLifeStart = Range("03 - Tracking Skill", "01 - Trail Duration At Level 0", 5f, "Ground mark lifetime at level zero.", 0.1f, 60f);
			_trailLifeEnd = Range("03 - Tracking Skill", "02 - Trail Duration At Level 100", 20f, "Ground mark lifetime at level 100.", 0.1f, 60f);
			_trackRangeStart = Range("03 - Tracking Skill", "03 - Trail Range At Level 0", 20f, "Trail recording range at level zero.", 1f, 100f);
			_trackRangeEnd = Range("03 - Tracking Skill", "04 - Trail Range At Level 100", 100f, "Trail recording range at level 100.", 1f, 100f);
			_instinctRangeStart = Range("03 - Tracking Skill", "05 - Instinct Range At Level 0", 20f, "Instinct detection distance at level zero.", 1f, 100f);
			_instinctRangeEnd = Range("03 - Tracking Skill", "06 - Instinct Range At Level 100", 100f, "Instinct detection distance at level 100.", 1f, 100f);
			_experience = Range("03 - Tracking Skill", "07 - Experience Per Use", 1f, "Experience for following marks or detecting creatures. Zero disables experience.", 0f, 10f);
			_staminaStart = Range("03 - Tracking Skill", "08 - Stamina Per Second At Level 0", 5f, "Stamina consumed per second at level zero.", 0f, 30f);
			_staminaEnd = Range("03 - Tracking Skill", "09 - Stamina Per Second At Level 100", 1f, "Stamina consumed per second at level 100.", 0f, 30f);
			_instinctEnabled = BindConfig("04 - Tracking Instinct", "01 - Enabled", value: true, "Show a spectral aura on hostile creatures and passive AnimalAI creatures.");
			_instinctColor = BindConfig("04 - Tracking Instinct", "03 - Aura Color", "#FF4020", "Aura color in #RRGGBB format.", synchronizedSetting: false);
			_maxGlows = BindConfig("05 - Performance", "01 - Maximum Auras", 64, new ConfigDescription("Maximum simultaneous creature and player auras, prioritizing nearby targets.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 256), Array.Empty<object>()));
			_playerTrackingEnabled = BindConfig("07 - Player Tracking", "01 - Enabled", value: false, "Detect other loaded players after completing localization. Players never grant tracking experience.");
			_playerMinimumLevel = BindConfig("07 - Player Tracking", "02 - Minimum Tracking Level", 25, new ConfigDescription("Minimum Tracking skill level required to detect players.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), Array.Empty<object>()));
			_playerDetectionRange = Range("07 - Player Tracking", "03 - Detection Range", 100f, "Maximum player detection and display distance in meters. Only players loaded on this client can be detected. Hard limit: 100 meters.", 1f, 100f);
			_playerAuraColor = BindConfig("07 - Player Tracking", "04 - Aura Color", "#FFD700", "Player aura color in #RRGGBB format. Invalid values use gold. This setting is local.", synchronizedSetting: false);
			_onlyPvpPlayers = BindConfig("07 - Player Tracking", "05 - Only PvP Players", value: false, "Detect only players whose PvP setting is enabled.");
		}

		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 BindConfig(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()), synced);
		}

		private void Awake()
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			HuntersInstinctAssets.Load(((BaseUnityPlugin)this).Logger);
			Localizer.Load();
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			try
			{
				SetupServerSync();
				Configure();
			}
			finally
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
			}
			((BaseUnityPlugin)this).Config.Save();
			SetupConfigWatcher();
			Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(InvalidateFocusText));
			_groundMask = LayerMask.GetMask(new string[4] { "terrain", "Default", "static_solid", "piece" });
			_harmony = new Harmony("radamanto.HuntersInstinct");
			_harmony.CreateClassProcessor(typeof(Skills_Awake_RegisterTracking)).Patch();
			_harmony.CreateClassProcessor(typeof(Skills_Load_RegisterTracking)).Patch();
			_harmony.CreateClassProcessor(typeof(Skills_IsSkillValid_AllowTracking)).Patch();
			_harmony.CreateClassProcessor(typeof(Skills_CheatRaiseSkill_Tracking)).Patch();
			_harmony.CreateClassProcessor(typeof(Skills_CheatResetSkill_Tracking)).Patch();
		}

		private void OnDestroy()
		{
			Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(InvalidateFocusText));
			_watcherReady = false;
			_configWatcher?.Dispose();
			_configWatcher = null;
			((MonoBehaviour)this).StopAllCoroutines();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			ClearSession();
			DisposeTrailResources();
			HuntersInstinctAssets.Dispose();
			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 void SetupServerSync()
		{
			//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);
		}

		[<f31aece1-10b3-45b1-b44f-172fd99b28e9>NullableContext(1)]
		private ConfigEntry<T> BindConfig<[<f280da0b-cf6f-4ac1-bf8c-0c34672954c6>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;
		}

		[<f31aece1-10b3-45b1-b44f-172fd99b28e9>NullableContext(1)]
		private ConfigEntry<T> BindConfig<[<f280da0b-cf6f-4ac1-bf8c-0c34672954c6>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 BindConfig(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.Error += delegate(object _, ErrorEventArgs args)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("Config watcher failed: " + args.GetException().Message));
				};
				_configWatcher.Changed += OnConfigFileChanged;
				_configWatcher.Created += OnConfigFileChanged;
				_configWatcher.Renamed += delegate(object _, RenamedEventArgs args)
				{
					OnConfigFileChanged(_, args);
				};
				_watcherReady = true;
				_configWatcher.EnableRaisingEvents = true;
			}
			catch (Exception ex)
			{
				_watcherReady = false;
				_configWatcher?.Dispose();
				_configWatcher = null;
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Automatic config reload unavailable: " + ex.Message));
			}
		}

		[<f31aece1-10b3-45b1-b44f-172fd99b28e9>NullableContext(1)]
		private void OnConfigFileChanged(object sender, FileSystemEventArgs args)
		{
			if (_watcherReady)
			{
				_lastCfgWrite = Stopwatch.GetTimestamp();
				if (!_reloadScheduled)
				{
					_reloadScheduled = true;
					((MonoBehaviour)this).StartCoroutine(ReloadConfigAfterQuietPeriod());
				}
			}
		}

		[<f31aece1-10b3-45b1-b44f-172fd99b28e9>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 (object)new WaitForSecondsRealtime(0.25f);
					}
					if (!_watcherReady)
					{
						break;
					}
					bool saveOnSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
					bool retry = false;
					try
					{
						((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
						((BaseUnityPlugin)this).Config.Reload();
					}
					catch (IOException ex)
					{
						IOException error = ex;
						retry = true;
						if (attempt == 2)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("Config reload failed after three attempts: " + error.Message));
						}
					}
					catch (Exception ex2)
					{
						Exception error2 = ex2;
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Config reload failed: " + error2.Message));
					}
					finally
					{
						((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnSet;
					}
					if (!retry)
					{
						break;
					}
					_lastCfgWrite = Stopwatch.GetTimestamp();
				}
			}
			finally
			{
				_reloadScheduled = false;
			}
		}

		private void OnGUI()
		{
			//IL_0339: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: 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_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: 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_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: 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 (_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);
			}
			if (_cachedInstinctColor != _instinctColor.Value)
			{
				_cachedInstinctColor = _instinctColor.Value;
				if (!ColorUtility.TryParseHtmlString(_cachedInstinctColor, ref _parsedInstinctColor))
				{
					_parsedInstinctColor = new Color(1f, 0.25f, 0.125f);
				}
			}
			Color val = PlayerAuraColor();
			Color color = 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())
					{
						continue;
					}
					bool flag = instinctTarget.IsPlayer();
					if (!flag || CanTrackPlayer(instinctTarget))
					{
						float distance = Vector3.Distance(((Component)instinctTarget).transform.position, ((Component)_activePlayer).transform.position);
						Color color2 = (flag ? val : _parsedInstinctColor);
						float range = (flag ? PlayerTrackingReach : _instinctReach);
						Vector3 val2 = main.WorldToScreenPoint(instinctTarget.GetCenterPoint());
						if (!(val2.z <= 0f) && !(val2.x < 0f) && !(val2.x > (float)Screen.width) && !(val2.y < 0f) && !(val2.y > (float)Screen.height))
						{
							float num = 60f * HuntersInstinctRules.AuraDistanceScale(distance, range) * 1.8f * (float)Screen.height / 1080f;
							((Vector2)(ref center))..ctor(val2.x, (float)Screen.height - val2.y);
							float num2 = HuntersInstinctRules.SmoothFade(_instinctMarks[instinctTarget].Phase);
							color2.a = 0.7225f * num2;
							GUI.color = color2;
							DrawCentered((Texture)(object)_auraTexture, center, num, num);
							float progress = HuntersInstinctVisuals.PulseProgress(Time.time, ((Object)instinctTarget).GetInstanceID());
							float num3 = num * HuntersInstinctVisuals.PulseScale(progress);
							color2.a = 0.85f * HuntersInstinctVisuals.PulseOpacity(progress) * num2;
							GUI.color = color2;
							DrawCentered((Texture)(object)_pulseTexture, center, num3, num3);
						}
					}
				}
			}
			finally
			{
				GUI.color = color;
				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 void SampleInstinctTargets(List<Character> characters)
		{
			//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_00b5: 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)
			if (!InstinctActive)
			{
				return;
			}
			Vector3 origin = ((Component)_activePlayer).transform.position;
			_instinctCandidates.Clear();
			_instinctCandidates.AddRange(_instinctTargets);
			foreach (Character character in characters)
			{
				if (!Object.op_Implicit((Object)(object)character))
				{
					continue;
				}
				if (character.IsPlayer())
				{
					if (!CanTrackPlayer(character))
					{
						continue;
					}
				}
				else
				{
					if (!_instinctEnabled.Value)
					{
						continue;
					}
					Vector3 val = ((Component)character).transform.position - origin;
					if (((Vector3)(ref val)).sqrMagnitude > _instinctReach * _instinctReach || !HuntersInstinctRules.CanDetectWithInstinct(Classify(character), character.GetBaseAI() is AnimalAI))
					{
						continue;
					}
				}
				if (_instinctMarks.TryGetValue(character, out var value))
				{
					value.Refresh(Time.time, _auraLifetime);
				}
				else
				{
					_instinctCandidates.Add(character);
				}
			}
			_instinctCandidates.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 val3 = ((Component)a).transform.position - origin;
				float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
				val3 = ((Component)b).transform.position - origin;
				return sqrMagnitude.CompareTo(((Vector3)(ref val3)).sqrMagnitude);
			});
			_selectedInstinctTargets.Clear();
			int num = Math.Min(_instinctCandidates.Count, _maxGlows.Value);
			for (int num2 = 0; num2 < num; num2++)
			{
				_selectedInstinctTargets.Add(_instinctCandidates[num2]);
			}
			for (int num3 = _instinctTargets.Count - 1; num3 >= 0; num3--)
			{
				if (!_selectedInstinctTargets.Contains(_instinctTargets[num3]))
				{
					_instinctMarks.Remove(_instinctTargets[num3]);
					_instinctTargets.RemoveAt(num3);
				}
			}
			_instinctTargets.Clear();
			for (int num4 = 0; num4 < num; num4++)
			{
				Character val2 = _instinctCandidates[num4];
				if (!_instinctMarks.TryGetValue(val2, out var value2))
				{
					value2 = new HuntersInstinctMark();
					value2.Refresh(Time.time, _auraLifetime);
					_instinctMarks.Add(val2, value2);
				}
				_instinctTargets.Add(val2);
			}
		}

		private void UpdateInstinctMarks(float now, bool validate)
		{
			for (int num = _instinctTargets.Count - 1; num >= 0; num--)
			{
				Character val = _instinctTargets[num];
				if (!Object.op_Implicit((Object)(object)val) || val.IsDead() || (validate && !CanRetainInstinctTarget(val)) || !_instinctMarks[val].Tick(now, Time.unscaledDeltaTime, 0.25f, 0.35f))
				{
					_instinctMarks.Remove(val);
					_instinctTargets.RemoveAt(num);
				}
			}
		}

		private void TrainTracking(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_03b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03be: 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_0306: 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_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: 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 (GroundMark 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.IsPlayer() && !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 bool IsExcluded(string prefab)
		{
			return _exclusions.Contains(_excludedPrefabs.Value, prefab);
		}

		private bool CanTrackMark(GroundMark 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(GroundMark 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 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 bool CanTrackPlayer(Character character)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_activePlayer))
			{
				Player val = (Player)(object)((character is Player) ? character : null);
				if (val != null && Object.op_Implicit((Object)(object)val) && !((Object)(object)((Character)val).m_nview == (Object)null) && ((Character)val).m_nview.IsValid())
				{
					bool value = _playerTrackingEnabled.Value;
					bool self = (Object)(object)val == (Object)(object)_activePlayer;
					bool dead = ((Character)val).IsDead();
					float trackingLevel = _trackingLevel;
					int value2 = _playerMinimumLevel.Value;
					Vector3 val2 = ((Component)val).transform.position - ((Component)_activePlayer).transform.position;
					return HuntersInstinctRules.CanDetectPlayer(value, self, dead, trackingLevel, value2, ((Vector3)(ref val2)).sqrMagnitude, PlayerTrackingReach, _onlyPvpPlayers.Value, ((Character)val).IsPVPEnabled());
				}
			}
			return false;
		}

		private bool CanRetainInstinctTarget(Character character)
		{
			return character.IsPlayer() ? CanTrackPlayer(character) : (_instinctEnabled.Value && Classify(character) != HuntersInstinctRules.Kind.Ignore);
		}

		private Color PlayerAuraColor()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (_cachedPlayerAuraColor != _playerAuraColor.Value)
			{
				_cachedPlayerAuraColor = _playerAuraColor.Value;
				if (!ColorUtility.TryParseHtmlString(_cachedPlayerAuraColor, ref _parsedPlayerAuraColor))
				{
					_parsedPlayerAuraColor = new Color(1f, 43f / 51f, 0f);
				}
			}
			return _parsedPlayerAuraColor;
		}

		private void ClearSession()
		{
			ClearTrails();
			_trackingActive = 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();
			_characterSnapshot.Clear();
			_instinctCandidates.Clear();
			_selectedInstinctTargets.Clear();
			_activePlayer = null;
		}

		private void Update()
		{
			//IL_00a1: 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_00ae: 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();
				return;
			}
			if ((Object)(object)_activePlayer != (Object)(object)localPlayer)
			{
				ClearSession();
				_activePlayer = localPlayer;
				_trainingOrigin = ((Component)localPlayer).transform.position;
				_nextExperience = Time.time + 5f;
				_nextSample = 0f;
				_nextTrailResourceAttempt = 0f;
			}
			float time = Time.time;
			bool flag = (int)_activationKey.Value != 0 && Input.GetKey(_activationKey.Value);
			bool flag2 = Application.isFocused && Time.timeScale > 0f && Object.op_Implicit((Object)(object)Hud.instance) && ((Character)localPlayer).TakeInput();
			bool flag3 = HuntersInstinctRules.ShouldSample(flag && flag2 && !_activation.RequiresRelease, _trails.Count > 0) && time >= _nextSample;
			if (flag3)
			{
				_nextSample = time + 0.2f;
				Skills skills = ((Character)localPlayer).GetSkills();
				if (!Object.op_Implicit((Object)(object)skills))
				{
					return;
				}
				float level = (_trackingLevel = skills.GetSkillLevel((SkillType)1978436211));
				_trackReach = HuntersInstinctRules.Reach(level, _trackRangeStart.Value, _trackRangeEnd.Value);
				_instinctReach = HuntersInstinctRules.Reach(level, _instinctRangeStart.Value, _instinctRangeEnd.Value);
				_focusDuration = HuntersInstinctRules.StaminaRate(level, _focusStart.Value, _focusEnd.Value);
				_auraLifetime = HuntersInstinctRules.Reach(level, _auraLifeStart.Value, _auraLifeEnd.Value);
				_trackingDuration = HuntersInstinctRules.Reach(level, _trackingStart.Value, _trackingEnd.Value);
				_trailLifetime = HuntersInstinctRules.Reach(level, _trailLifeStart.Value, _trailLifeEnd.Value);
				_staminaPerSecond = HuntersInstinctRules.StaminaRate(level, _staminaStart.Value, _staminaEnd.Value);
			}
			HuntersInstinctActivation.Result result = _activation.Tick(flag, flag2, localPlayer.GetStamina(), _staminaPerSecond, Time.deltaTime, Game.m_staminaRate);
			bool trackingActive = _trackingActive;
			float num = HuntersInstinctRules.PostureMultiplier(((Character)localPlayer).IsCrouching(), ((Character)localPlayer).IsRunning(), _crouchingMultiplier.Value, _walkingMultiplier.Value, _runningMultiplier.Value, IsFeatherFalling(localPlayer), _featherFallMultiplier.Value);
			_trackingActive = _focus.Advance(result.Active, Time.deltaTime, _focusDuration * num);
			bool flag4 = _trackingActive && !trackingActive;
			if (result.Active)
			{
				_focusBarProgress = _focus.Progress;
			}
			_focusBarAlpha = HuntersInstinctRules.StepFade(_focusBarAlpha, result.Active && !_trackingActive, Time.unscaledDeltaTime, 0.25f, 0.35f);
			UpdateFocusLabel();
			if (result.StaminaCost > 0f)
			{
				((Character)localPlayer).UseStamina(result.StaminaCost);
			}
			bool flag5 = time >= _nextEligibilityCheck;
			if (flag5)
			{
				_nextEligibilityCheck = time + 0.2f;
				RefreshMarkEligibility();
				if (_instinctTargets.Count > 0)
				{
					_trackingLevel = ((Character)localPlayer).GetSkills().GetSkillLevel((SkillType)1978436211);
				}
			}
			UpdateInstinctMarks(time, flag5);
			if (_trailsEnabled.Value && (result.Active || _trails.Count > 0))
			{
				EnsureTrailResources(time);
			}
			if (flag3 || flag4)
			{
				_characterSnapshot.Clear();
				_characterSnapshot.AddRange(Character.GetAllCharacters());
				SampleTrails(time, _characterSnapshot);
				if (_trackingActive)
				{
					SampleInstinctTargets(_characterSnapshot);
					TrainTracking(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 static bool IsTrackingName(string name)
		{
			return string.Equals(name, "Tracking", StringComparison.OrdinalIgnoreCase);
		}

		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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: 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 = (Object.op_Implicit((Object)(object)HuntersInstinctAssets.TrackingIcon) ? HuntersInstinctAssets.TrackingIcon : val?.m_icon),
					m_description = "$huntersinstinct_skill_description",
					m_increseStep = 1f
				});
			}
		}

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

		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 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 InvalidateFocusText()
		{
			_focusTextDirty = 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_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: 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)
			//IL_0379: 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_FontAsset val2 = (Object.op_Implicit((Object)(object)_titleFont) ? _titleFont : ((TMP_Text)hoverName).font);
				Material val3 = ((!Object.op_Implicit((Object)(object)_titleFont)) ? ((TMP_Text)hoverName).fontSharedMaterial : (Object.op_Implicit((Object)(object)_titleMaterial) ? _titleMaterial : ((TMP_Asset)_titleFont).material));
				if ((Object)(object)((TMP_Text)_focusLabel).font != (Object)(object)val2)
				{
					((TMP_Text)_focusLabel).font = val2;
				}
				if ((Object)(object)((TMP_Text)_focusLabel).fontSharedMaterial != (Object)(object)val3)
				{
					((TMP_Text)_focusLabel).fontSharedMaterial = val3;
				}
				if (_focusScreenHeight != Screen.height)
				{
					_focusScreenHeight = Screen.height;
					float num = (float)Screen.height / 1080f;
					((TMP_Text)_focusLabel).fontSize = 20f * num;
					((TMP_Text)_focusLabel).fontStyle = (FontStyles)0;
					RectTransform rectTransform = ((TMP_Text)_focusLabel).rectTransform;
					Vector2 val4 = default(Vector2);
					((Vector2)(ref val4))..ctor(0.5f, 0.5f);
					rectTransform.pivot = val4;
					Vector2 anchorMin = (rectTransform.anchorMax = val4);
					rectTransform.anchorMin = anchorMin;
					rectTransform.anchoredPosition = new Vector2(0f, -69f * num);
					rectTransform.sizeDelta = new Vector2(280f * num, 26f * num);
				}
				if (_focusTextDirty)
				{
					_focusTextDirty = false;
					((TMP_Text)_focusLabel).text = Localization.instance.Localize("$huntersinstinct_locating");
				}
				((Graphic)_focusLabel).color = new Color(1f, 0.72f, 0.35f, _focusBarAlpha);
			}
		}
	}
	internal static class HuntersInstinctAssets
	{
		private const string BundleName = "rd_hunter_instinct";

		private static AssetBundle _bundle;

		private static Stream _bundleStream;

		private static bool _createdSprite;

		internal static Sprite TrackingIcon { get; private set; }

		internal static void Load(ManualLogSource logger)
		{
			//IL_00e0: 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)
			try
			{
				Assembly assembly = typeof(HuntersInstinctAssets).Assembly;
				string text = assembly.GetName().Name + ".assets.rd_hunter_instinct";
				_bundleStream = assembly.GetManifestResourceStream(text);
				if (_bundleStream == null)
				{
					throw new InvalidOperationException("Embedded bundle not found: " + text);
				}
				_bundle = AssetBundle.LoadFromStream(_bundleStream);
				if (!Object.op_Implicit((Object)(object)_bundle))
				{
					throw new InvalidOperationException("Could not load rd_hunter_instinct");
				}
				TrackingIcon = _bundle.LoadAsset<Sprite>("ico_tracker");
				if (!Object.op_Implicit((Object)(object)TrackingIcon))
				{
					Texture2D val = _bundle.LoadAsset<Texture2D>("ico_tracker");
					if (Object.op_Implicit((Object)(object)val))
					{
						TrackingIcon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
						_createdSprite = true;
					}
				}
				if (!Object.op_Implicit((Object)(object)TrackingIcon))
				{
					throw new InvalidOperationException("ico_tracker is missing from the bundle.");
				}
			}
			catch (Exception ex)
			{
				Dispose();
				logger.LogWarning((object)("Custom skill icon unavailable; using vanilla fallback: " + ex.Message));
			}
		}

		internal static void Dispose()
		{
			if (_createdSprite && Object.op_Implicit((Object)(object)TrackingIcon))
			{
				Object.Destroy((Object)(object)TrackingIcon);
			}
			TrackingIcon = null;
			if (Object.op_Implicit((Object)(object)_bundle))
			{
				_bundle.Unload(false);
			}
			_bundle = null;
			_bundleStream?.Dispose();
			_bundleStream = null;
			_createdSprite = false;
		}
	}
}
namespace LocalizationManager
{
	[PublicAPI]
	[<f31aece1-10b3-45b1-b44f-172fd99b28e9>NullableContext(1)]
	[<f280da0b-cf6f-4ac1-bf8c-0c34672954c6>Nullable(0)]
	public class Localizer
	{
		private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors;

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

		private static readonly ConditionalWeakTable<Localization, string> localizationLanguage;

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

		[<f280da0b-cf6f-4ac1-bf8c-0c34672954c6>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([<f31aece1-10b3-45b1-b44f-172fd99b28e9>NullableContext(0)] (TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t)));
				}
				return _plugin;
			}
		}

		[<f280da0b-cf6f-4ac1-bf8c-0c34672954c6>Nullable(2)]
		[method: <f31aece1-10b3-45b1-b44f-172fd99b28e9>NullableContext(2)]
		[field: <f280da0b-cf6f-4ac1-bf8c-0c34672954c6>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, [<f31aece1-10b3-45b1-b44f-172fd99b28e9>NullableContext(0)] (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value()));
			}
			localization.AddWord(key, text);
		}

		public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, [<f280da0b-cf6f-4ac1-bf8c-0c34672954c6>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 += [<f31aece1-10b3-45b1-b44f-172fd99b28e9>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 (!target.m_translations.ContainsKey(key))
					{
						dictionary[key] = text;
						target.AddWord(key, text);
					}
				}
				else
				{
					list.Add(localizationObject);
				}
			}
			foreach (WeakReference<Localization> item in list)
			{
				localizationObjects.Remove(item);
			}
		}

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

		public static void LoadLocalizationLater()
		{
			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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>();
			loadedTexts = new Dictionary<string, Dictionary<string, string>>();
			localizationLanguage = new ConditionalWeakTable<Localization, string>();
			localizationObjects = new List<WeakReference<Localization>>();
			fileExtensions = new List<string>(2) { ".json", ".yml" };
			Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager");
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		[return: <f280da0b-cf6f-4ac1-bf8c-0c34672954c6>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;
		}

		[<f31aece1-10b3-45b1-b44f-172fd99b28e9>NullableContext(2)]
		public static byte[] ReadEmbeddedFileBytes([<f280da0b-cf6f-4ac1-bf8c-0c34672954c6>Nullable(1)] string resourceFileName, Assembly containingAssembly = null)
		{
			using MemoryStream memoryStream = new MemoryStream();
			if ((object)containingAssembly == null)
			{
				containingAssembly = Assembly.GetCallingAssembly();
			}
			string text = containingAssembly.GetManifestResourceNames().FirstOrDefault([<f31aece1-10b3-45b1-b44f-172fd99b28e9>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
	{
		[<f280da0b-cf6f-4ac1-bf8c-0c34672954c6>Nullable(1)]
		public const string Version = "1.4.1";
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<bd73d92e-976d-40ae-b5b6-8e0e913c9978>Embedded]
	internal sealed class <bd73d92e-976d-40ae-b5b6-8e0e913c9978>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)]
	[<bd73d92e-976d-40ae-b5b6-8e0e913c9978>Embedded]
	[CompilerGenerated]
	internal sealed class <2b5be3b3-e3c0-4b17-a210-0f00a81eaa05>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <2b5be3b3-e3c0-4b17-a210-0f00a81eaa05>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <2b5be3b3-e3c0-4b17-a210-0f00a81eaa05>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[<bd73d92e-976d-40ae-b5b6-8e0e913c9978>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	[CompilerGenerated]
	internal sealed class <08d7baa3-e242-464a-a12e-144ff4ebe798>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <08d7baa3-e242-464a-a12e-144ff4ebe798>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	[<bd73d92e-976d-40ae-b5b6-8e0e913c9978>Embedded]
	[CompilerGenerated]
	internal sealed class <6a090d86-6b76-4503-8fec-8e6293956058>RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public <6a090d86-6b76-4503-8fec-8e6293956058>RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ServerSync
{
	[PublicAPI]
	[<2b5be3b3-e3c0-4b17-a210-0f00a81eaa05>Nullable(0)]
	[<08d7baa3-e242-464a-a12e-144ff4ebe798>NullableContext(1)]
	internal abstract class OwnConfigEntryBase
	{
		[<2b5be3b3-e3c0-4b17-a210-0f00a81eaa05>Nullable(2)]
		public object LocalBaseValue;

		public bool SynchronizedConfig = true;

		public abstract ConfigEntryBase BaseConfig { get; }
	}
	[<08d7baa3-e242-464a-a12e-144ff4ebe798>NullableContext(1)]
	[<2b5be3b3-e3c0-4b17-a210-0f00a81eaa05>Nullable(0)]
	[PublicAPI]
	internal class SyncedConfigEntry<[<2b5be3b3-e3c0-4b17-a210-0f00a81eaa05>Nullable(2)] T>(ConfigEntry<T> sourceConfig) : OwnConfigEntryBase()
	{
		public readonly ConfigEntry