Decompiled source of Sensible Hunting v1.2.1

BepInEx/plugins/SensibleHunting.dll

Decompiled 5 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SensibleHunting")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.1.0")]
[assembly: AssemblyInformationalVersion("1.2.1+bab718a2e1263b6295ce4042ae47cd1a6a74aa0a")]
[assembly: AssemblyProduct("SensibleHunting")]
[assembly: AssemblyTitle("SensibleHunting")]
[assembly: AssemblyVersion("1.2.1.0")]
namespace SensibleHunting;

[HarmonyPatch]
internal static class HuntingXp
{
	private static readonly FieldRef<Character, HitData> LastHit = AccessTools.FieldRefAccess<Character, HitData>("m_lastHit");

	private static ZDOID _lastStalked = ZDOID.None;

	private static Vector3 _lastStalkPos = Vector3.zero;

	private static void Award(Player player, float factor)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		if (factor > 0f)
		{
			((Character)player).GetSkills().RaiseSkill(SensibleHuntingPlugin.Hunting, factor);
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Player), "RaiseSkill")]
	private static void OnSneakTick(Player __instance, SkillType skill, float value)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Invalid comparison between Unknown and I4
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		if ((int)skill != 101)
		{
			return;
		}
		SensibleHuntingPlugin instance = SensibleHuntingPlugin.Instance;
		if ((Object)(object)instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
		{
			return;
		}
		Character val = instance.NearestGame(__instance, instance.CurrentRange(__instance));
		if (!((Object)(object)val == (Object)null))
		{
			ZDOID zDOID = val.GetZDOID();
			Vector3 position = ((Component)__instance).transform.position;
			bool flag = Vector3.Distance(position, _lastStalkPos) >= instance.StalkMoveDistance.Value;
			if (!(zDOID == _lastStalked) || flag)
			{
				_lastStalked = zDOID;
				_lastStalkPos = position;
				Award(__instance, value * instance.StalkFactor.Value);
			}
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Character), "Damage")]
	private static void OnDamage(Character __instance, HitData hit)
	{
		SensibleHuntingPlugin instance = SensibleHuntingPlugin.Instance;
		if (!((Object)(object)instance == (Object)null) && hit != null && !((Object)(object)hit.GetAttacker() != (Object)(object)Player.m_localPlayer) && !((Object)(object)Player.m_localPlayer == (Object)null) && SensibleHuntingPlugin.IsWildGame(__instance))
		{
			Award(Player.m_localPlayer, HuntMath.HitXp(hit.GetTotalDamage(), __instance.GetMaxHealth(), instance.HitFactor.Value));
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Character), "OnDeath")]
	private static void OnDeath(Character __instance)
	{
		SensibleHuntingPlugin instance = SensibleHuntingPlugin.Instance;
		if (!((Object)(object)instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && SensibleHuntingPlugin.IsGame(__instance))
		{
			HitData obj = LastHit.Invoke(__instance);
			if (!((Object)(object)((obj != null) ? obj.GetAttacker() : null) != (Object)(object)Player.m_localPlayer))
			{
				Award(Player.m_localPlayer, HuntMath.KillXp(__instance.GetLevel(), instance.KillFactor.Value));
			}
		}
	}
}
internal static class HuntMath
{
	internal struct Blip
	{
		public float X;

		public float Y;

		public float Angle;

		public bool OffScreen;
	}

	internal static Blip Project(float vx, float vy, float vz, float width, float height, float margin)
	{
		float num = (vx - 0.5f) * width;
		float num2 = (vy - 0.5f) * height;
		if (vz < 0f)
		{
			num = 0f - num;
			num2 = 0f - num2;
			if (num * num + num2 * num2 < 1f)
			{
				num2 = -1f;
			}
			float num3 = width + height;
			float num4 = Mathf.Sqrt(num * num + num2 * num2);
			num = num / num4 * num3;
			num2 = num2 / num4 * num3;
		}
		float num5 = Mathf.Max(1f, width * 0.5f - margin);
		float num6 = Mathf.Max(1f, height * 0.5f - margin);
		float num7 = Mathf.Max(Mathf.Abs(num) / num5, Mathf.Abs(num2) / num6);
		bool flag = num7 > 1f;
		if (flag)
		{
			num /= num7;
			num2 /= num7;
		}
		return new Blip
		{
			X = width * 0.5f + num,
			Y = height * 0.5f + num2,
			Angle = Mathf.Atan2(num2, num) * 57.29578f,
			OffScreen = flag
		};
	}

	internal static float Daylight(float dayFraction)
	{
		return Mathf.Sqrt(Mathf.Clamp01(1f - Mathf.Abs(dayFraction - 0.5f) / 0.25f));
	}

	internal static bool InView(float vx, float vy, float vz)
	{
		if (vz > 0f && vx >= 0f && vx <= 1f && vy >= 0f)
		{
			return vy <= 1f;
		}
		return false;
	}

	internal static float BySkill(float skillFactor, float at0, float at100)
	{
		return Mathf.Lerp(at0, at100, Mathf.Clamp01(skillFactor));
	}

	internal static int PulseIndex(float time, float onDuration, float gap)
	{
		return Mathf.FloorToInt(time / Mathf.Max(0.01f, onDuration + gap));
	}

	internal static float PulseAlpha(float time, float onDuration, float gap, float fade)
	{
		float num = Mathf.Max(0.01f, onDuration + gap);
		float num2 = Mathf.Repeat(time, num);
		if (num2 >= onDuration)
		{
			return 0f;
		}
		if (fade <= 0f)
		{
			return 1f;
		}
		float num3 = Mathf.Min(num2 / fade, (onDuration - num2) / fade);
		return Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(num3));
	}

	internal static int DetailTier(float skillFactor)
	{
		if (!(skillFactor < 0.25f))
		{
			if (!(skillFactor < 0.5f))
			{
				if (!(skillFactor < 0.75f))
				{
					return 3;
				}
				return 2;
			}
			return 1;
		}
		return 0;
	}

	internal static float ErrorForTier(int tier, float maxDegrees)
	{
		if (tier > 0)
		{
			if (tier != 1)
			{
				return 0f;
			}
			return maxDegrees * 0.35f;
		}
		return maxDegrees;
	}

	internal static float BearingErrorDegrees(int seed, float maxDegrees)
	{
		int num = seed * -1640531535;
		int num2 = (num ^ (num >>> 15)) * -2048144777;
		return ((float)((uint)(num2 ^ (num2 >>> 13)) % 20001u) / 10000f - 1f) * maxDegrees;
	}

	internal static string Ballpark(float distance, float step)
	{
		if (step <= 0f)
		{
			step = 1f;
		}
		return "~" + Mathf.RoundToInt(distance / step) * (int)step + " m";
	}

	internal static string Exact(float distance)
	{
		return Mathf.RoundToInt(distance) + " m";
	}

	internal static float BlipScale(float distance, float range, float min, float max)
	{
		return Mathf.Lerp(max, min, (range <= 0f) ? 1f : Mathf.Clamp01(distance / range));
	}

	internal static float DistanceFade(float distance, float range)
	{
		return 1f - Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(range * 0.75f, range, distance));
	}

	internal static float HitXp(float damage, float maxHealth, float factor)
	{
		if (!(maxHealth <= 0f))
		{
			return Mathf.Clamp01(damage / maxHealth) * factor;
		}
		return 0f;
	}

	internal static HashSet<string> ParseNames(string list)
	{
		HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
		if (string.IsNullOrEmpty(list))
		{
			return hashSet;
		}
		string[] array = list.Split(new char[1] { ',' });
		for (int i = 0; i < array.Length; i++)
		{
			string text = array[i].Trim();
			if (text.Length > 0)
			{
				hashSet.Add(text);
			}
		}
		return hashSet;
	}

	internal static float KillXp(int level, float factor)
	{
		return factor * (float)Mathf.Max(1, level);
	}
}
internal class ProbeCommand : ConsoleCommand
{
	public override string Name => "sh_probe";

	public override string Help => "Sensible Hunting diagnostics: sh_probe [name filter]";

	public override bool IsSecret => true;

	private static void Print(string line)
	{
		if ((Object)(object)Console.instance != (Object)null)
		{
			Console.instance.Print(line);
		}
		ManualLogSource log = SensibleHuntingPlugin.Log;
		if (log != null)
		{
			log.LogInfo((object)line);
		}
	}

	public override void Run(string[] args)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0238: Unknown result type (might be due to invalid IL or missing references)
		//IL_023d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0319: Unknown result type (might be due to invalid IL or missing references)
		//IL_031e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0376: Unknown result type (might be due to invalid IL or missing references)
		//IL_037b: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		SensibleHuntingPlugin instance = SensibleHuntingPlugin.Instance;
		if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null)
		{
			Print("sh_probe: no local player");
			return;
		}
		Vector3 position = ((Component)localPlayer).transform.position;
		float num = instance.CurrentRange(localPlayer);
		Print($"sh_probe: skill {((Character)localPlayer).GetSkillLevel(SensibleHuntingPlugin.Hunting):0} range {num:0} m " + $"sensing {instance.IsSensing(localPlayer)} game list [{instance.GameAnimals.Value}]");
		List<Character> list = new List<Character>();
		Character.GetCharactersInRange(position, num, list);
		Print($"characters in range: {list.Count}");
		foreach (Character item in list)
		{
			BaseAI baseAI = item.GetBaseAI();
			Print($"  {Utils.GetPrefabName(((Component)item).gameObject),-18} {Vector3.Distance(((Component)item).transform.position, position),5:0} m " + string.Format("ai={0,-10} game={1,-5} ", ((Object)(object)baseAI == (Object)null) ? "none" : ((object)baseAI).GetType().Name, SensibleHuntingPlugin.IsGame(item)) + $"sensed={SensibleHuntingPlugin.CanSense(item),-5} flying={item.IsFlying(),-5} onGround={item.IsOnGround(),-5} " + $"tamed={item.IsTamed(),-5} dead={item.IsDead()}");
		}
		Print($"ambient birds loaded: {RandomFlyingBird.Instances.Count}");
		foreach (IMonoUpdater instance2 in RandomFlyingBird.Instances)
		{
			RandomFlyingBird val = (RandomFlyingBird)(object)((instance2 is RandomFlyingBird) ? instance2 : null);
			if (val != null)
			{
				ZNetView component = ((Component)val).GetComponent<ZNetView>();
				bool flag = (Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetBool(ZDOVars.s_landed, false);
				Print($"  {Utils.GetPrefabName(((Component)val).gameObject),-18} {Vector3.Distance(((Component)val).transform.position, position),5:0} m " + $"listed={SensibleHuntingPlugin.IsGameName(((Component)val).gameObject),-5} " + $"zdo={(Object)(object)component != (Object)null && component.IsValid(),-5} landed={flag}");
			}
		}
		string text = ((args != null && args.Length != 0) ? args[0] : null);
		if (string.IsNullOrEmpty(text))
		{
			Print("pass a name filter to dump components, e.g. sh_probe seagal");
			return;
		}
		int num2 = 0;
		ZNetView[] array = Object.FindObjectsOfType<ZNetView>();
		foreach (ZNetView val2 in array)
		{
			string prefabName = Utils.GetPrefabName(((Component)val2).gameObject);
			if (prefabName.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0 && !(Vector3.Distance(((Component)val2).transform.position, position) > 300f))
			{
				num2++;
				string arg = string.Join(", ", from c in ((Component)val2).GetComponents<Component>()
					select ((object)c).GetType().Name);
				Print($"  {prefabName} {Vector3.Distance(((Component)val2).transform.position, position):0} m [{arg}]");
			}
		}
		Print($"objects matching \"{text}\": {num2}");
	}
}
[BepInPlugin("com.mous.sensiblehunting", "Sensible Hunting", "1.2.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class SensibleHuntingPlugin : BaseUnityPlugin
{
	private class BlipView
	{
		public RectTransform Root;

		public TextMeshProUGUI Wave;

		public TextMeshProUGUI Label;

		public Image Icon;

		public void SetActive(bool on)
		{
			if (((Component)Root).gameObject.activeSelf != on)
			{
				((Component)Root).gameObject.SetActive(on);
			}
		}
	}

	private struct Sighting
	{
		public Vector3 Position;

		public Sprite Icon;

		public bool Gold;

		public Character Seen;
	}

	public const string PluginGuid = "com.mous.sensiblehunting";

	public const string PluginName = "Sensible Hunting";

	public const string PluginVersion = "1.2.1";

	internal const string SkillIdentifier = "com.mous.sensiblehunting.hunting";

	internal static SkillType Hunting;

	internal static ManualLogSource Log;

	internal static SensibleHuntingPlugin Instance;

	private static readonly Color Gold = new Color(1f, 0.79f, 0.25f);

	private const float PulseFade = 0.3f;

	internal ConfigEntry<bool> Enabled;

	internal ConfigEntry<float> MinRange;

	internal ConfigEntry<float> MaxRange;

	internal ConfigEntry<float> EdgeMargin;

	internal ConfigEntry<float> NearSize;

	internal ConfigEntry<float> FarSize;

	internal ConfigEntry<float> Opacity;

	internal ConfigEntry<bool> RequireCrouch;

	internal ConfigEntry<string> GameAnimals;

	internal ConfigEntry<float> MaxBearingError;

	internal ConfigEntry<float> DaytimeErrorScale;

	internal ConfigEntry<float> SightRadius;

	internal ConfigEntry<float> PulseOnAtZero;

	internal ConfigEntry<float> PulseOnAtHundred;

	internal ConfigEntry<float> PulseGapAtZero;

	internal ConfigEntry<float> PulseGapAtHundred;

	internal ConfigEntry<float> BallparkStep;

	internal ConfigEntry<string> Glyph;

	internal ConfigEntry<string> EdgeGlyph;

	internal ConfigEntry<float> StalkFactor;

	internal ConfigEntry<float> HitFactor;

	internal ConfigEntry<float> KillFactor;

	internal ConfigEntry<float> StalkMoveDistance;

	private Harmony _harmony;

	private static int _viewBlockMask;

	private RectTransform _root;

	private readonly List<BlipView> _blips = new List<BlipView>();

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

	private static HashSet<string> _gameNames;

	private readonly List<Sighting> _sightings = new List<Sighting>();

	private int _pulseIndex = -1;

	private void Awake()
	{
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Expected O, but got Unknown
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Expected O, but got Unknown
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Expected O, but got Unknown
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Expected O, but got Unknown
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Expected O, but got Unknown
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: Expected O, but got Unknown
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0244: Expected O, but got Unknown
		//IL_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: Expected O, but got Unknown
		//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Expected O, but got Unknown
		//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fe: Expected O, but got Unknown
		//IL_0332: Unknown result type (might be due to invalid IL or missing references)
		//IL_033c: Expected O, but got Unknown
		//IL_0370: Unknown result type (might be due to invalid IL or missing references)
		//IL_037a: Expected O, but got Unknown
		//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b8: Expected O, but got Unknown
		//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f6: Expected O, but got Unknown
		//IL_0474: Unknown result type (might be due to invalid IL or missing references)
		//IL_047e: Expected O, but got Unknown
		//IL_04b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04bc: Expected O, but got Unknown
		//IL_04f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fa: Expected O, but got Unknown
		//IL_052e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0538: Expected O, but got Unknown
		//IL_0542: Unknown result type (might be due to invalid IL or missing references)
		//IL_0547: Unknown result type (might be due to invalid IL or missing references)
		//IL_0552: Unknown result type (might be due to invalid IL or missing references)
		//IL_055d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0568: Unknown result type (might be due to invalid IL or missing references)
		//IL_0578: Expected O, but got Unknown
		//IL_0573: Unknown result type (might be due to invalid IL or missing references)
		//IL_0578: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0602: Expected O, but got Unknown
		Instance = this;
		Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "Show hunting indicators.");
		MinRange = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "MinRange", 30f, new ConfigDescription("Detection radius at skill 0 (metres).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 100f), Array.Empty<object>()));
		MaxRange = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "MaxRange", 90f, new ConfigDescription("Detection radius at skill 100 (metres). Only creatures loaded around you can be sensed: at the default Simulation Distance that is every direction to ~128 m and some directions to ~270 m.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 175f), Array.Empty<object>()));
		GameAnimals = ((BaseUnityPlugin)this).Config.Bind<string>("1 - General", "GameAnimals", "Boar,Neck,Lox,Asksvin,Wolf,Seagal,Moose,Seal", "Creatures that fight back but still count as game, plus anything that is not a plain ground animal (prefab names, comma separated - Seagal is the seagull, spelled that way in the game files). Anything with the passive animal AI - deer, hares, chickens, young animals - always counts.");
		GameAnimals.SettingChanged += delegate
		{
			_gameNames = null;
		};
		RequireCrouch = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "RequireCrouch", true, "Only sense game while crouched. Standing up stops the instinct.");
		MaxBearingError = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "MaxBearingError", 10f, new ConfigDescription("How far off a blip may point at skill 0, in degrees. Shrinks as the skill rises, gone by 50.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 90f), Array.Empty<object>()));
		DaytimeErrorScale = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "DaytimeErrorScale", 2f, new ConfigDescription("Multiplier on MaxBearingError at midday, ramping down to 1x through dusk and back up through dawn. Set to 1 for no day/night difference. Only bites below skill 50, where the bearing error exists at all.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
		SightRadius = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "SightRadius", 0.3f, new ConfigDescription("Thickness of the line-of-sight probe, in metres. A hair-thin ray (0) slips past tree trunks; wider counts more things as cover, but an animal standing tight against the ground or a wall starts reading as hidden.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
		BallparkStep = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "BallparkStep", 5f, new ConfigDescription("Rounding of the rough distance shown at skill 25-49 (metres).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 25f), Array.Empty<object>()));
		PulseOnAtZero = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Pulse", "VisibleAtSkill0", 0.8f, new ConfigDescription("Seconds a blip stays up per pulse at skill 0.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
		PulseOnAtHundred = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Pulse", "VisibleAtSkill100", 2.5f, new ConfigDescription("Seconds a blip stays up per pulse at skill 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
		PulseGapAtZero = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Pulse", "GapAtSkill0", 6f, new ConfigDescription("Seconds of nothing between pulses at skill 0.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>()));
		PulseGapAtHundred = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Pulse", "GapAtSkill100", 1.5f, new ConfigDescription("Seconds of nothing between pulses at skill 100.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>()));
		EdgeMargin = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Layout", "EdgeMargin", 64f, new ConfigDescription("Keep edge indicators this far inside the screen, in HUD units (screen is 1920x1080 units at GUI scale 1).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>()));
		NearSize = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Layout", "NearSize", 34f, new ConfigDescription("Size of a blip right next to you.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 96f), Array.Empty<object>()));
		FarSize = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Layout", "FarSize", 16f, new ConfigDescription("Size of a blip at the edge of your detection range.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 96f), Array.Empty<object>()));
		Opacity = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Layout", "Opacity", 0.85f, new ConfigDescription("Overall opacity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
		Glyph = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Layout", "Glyph", "((•))", "Blip drawn over an animal you can see.");
		EdgeGlyph = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Layout", "EdgeGlyph", "•)))", "Blip pinned to the screen edge; it is rotated to point at the animal.");
		StalkFactor = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Experience", "StalkFactor", 0.25f, new ConfigDescription("Fraction of the sneak XP tick also awarded as hunting XP while an animal is detected.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>()));
		HitFactor = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Experience", "HitFactor", 1f, new ConfigDescription("XP for hitting a wild animal, scaled by the fraction of its health removed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
		KillFactor = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Experience", "KillFactor", 4f, new ConfigDescription("XP for killing a wild animal, multiplied by its star level.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
		StalkMoveDistance = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Experience", "StalkMoveDistance", 5f, new ConfigDescription("Anti-AFK: stalking only pays again once you have moved this far or the nearest animal changed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
		Hunting = SkillManager.Instance.AddSkill(new SkillConfig
		{
			Identifier = "com.mous.sensiblehunting.hunting",
			Name = "Hunting",
			Description = "Reading the woods. Higher hunting senses wild game further away, points at it more truly, and tells you what it is.",
			IncreaseStep = 1f
		});
		_viewBlockMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" });
		Log = ((BaseUnityPlugin)this).Logger;
		SpeciesIcons.Load(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), ((BaseUnityPlugin)this).Logger);
		CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new ProbeCommand());
		_harmony = new Harmony("com.mous.sensiblehunting");
		_harmony.PatchAll(typeof(HuntingXp));
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Sensible Hunting 1.2.1 loaded");
	}

	private void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	internal static bool IsGame(Character c)
	{
		if ((Object)(object)c == (Object)null || c.IsPlayer() || c.IsTamed())
		{
			return false;
		}
		if (c.GetBaseAI() is AnimalAI)
		{
			return true;
		}
		return IsGameName(((Component)c).gameObject);
	}

	internal static bool IsGameName(GameObject go)
	{
		if (_gameNames == null)
		{
			_gameNames = HuntMath.ParseNames(Instance.GameAnimals.Value);
		}
		return _gameNames.Contains(Utils.GetPrefabName(go));
	}

	internal static bool IsWildGame(Character c)
	{
		if (IsGame(c))
		{
			return !c.IsDead();
		}
		return false;
	}

	internal static bool CanSense(Character c)
	{
		if (IsWildGame(c))
		{
			if (c.IsFlying())
			{
				return c.IsOnGround();
			}
			return true;
		}
		return false;
	}

	internal Character NearestGame(Player player, float range)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: 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)
		_scratch.Clear();
		Character.GetCharactersInRange(((Component)player).transform.position, range, _scratch);
		Character result = null;
		float num = float.MaxValue;
		foreach (Character item in _scratch)
		{
			if (CanSense(item))
			{
				Vector3 val = ((Component)item).transform.position - ((Component)player).transform.position;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (!(sqrMagnitude >= num))
				{
					num = sqrMagnitude;
					result = item;
				}
			}
		}
		return result;
	}

	internal float CurrentRange(Player player)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		return HuntMath.BySkill(((Character)player).GetSkillFactor(Hunting), MinRange.Value, MaxRange.Value);
	}

	internal bool IsSensing(Player player)
	{
		if (RequireCrouch.Value)
		{
			return ((Character)player).IsCrouching();
		}
		return true;
	}

	internal static bool CanSee(Vector3 eye, Vector3 point, float radius)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: 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)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = point - eye;
		float magnitude = ((Vector3)(ref val)).magnitude;
		if (magnitude < 0.01f)
		{
			return true;
		}
		Vector3 val2 = val / magnitude;
		RaycastHit val3 = default(RaycastHit);
		if (radius <= 0f)
		{
			if (Physics.Raycast(eye, val2, magnitude, _viewBlockMask))
			{
				return false;
			}
		}
		else if (Physics.SphereCast(eye, radius, val2, ref val3, Mathf.Max(0.01f, magnitude - radius), _viewBlockMask))
		{
			return false;
		}
		return !ParticleMist.IsMistBlocked(eye, point);
	}

	private void Update()
	{
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: 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_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: 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_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0342: 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_041c: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		Camera main = Camera.main;
		if ((Object)(object)Hud.instance == (Object)null || (Object)(object)localPlayer == (Object)null || (Object)(object)main == (Object)null || ((Object)(object)_root == (Object)null && !TryCreate()))
		{
			return;
		}
		bool flag = Enabled.Value && !Minimap.IsOpen() && !((Character)localPlayer).IsDead() && IsSensing(localPlayer);
		if (((Component)_root).gameObject.activeSelf != flag)
		{
			((Component)_root).gameObject.SetActive(flag);
		}
		if (!flag)
		{
			_pulseIndex = -1;
			return;
		}
		float skillFactor = ((Character)localPlayer).GetSkillFactor(Hunting);
		float range = CurrentRange(localPlayer);
		int num = HuntMath.DetailTier(skillFactor);
		float onDuration = HuntMath.BySkill(skillFactor, PulseOnAtZero.Value, PulseOnAtHundred.Value);
		float gap = HuntMath.BySkill(skillFactor, PulseGapAtZero.Value, PulseGapAtHundred.Value);
		Vector3 position = ((Component)localPlayer).transform.position;
		int num2 = HuntMath.PulseIndex(Time.time, onDuration, gap);
		if (num2 != _pulseIndex)
		{
			_pulseIndex = num2;
			Sense(position, ((Character)localPlayer).m_eye.position, main, range, num);
		}
		float num3 = HuntMath.PulseAlpha(Time.time, onDuration, gap, 0.3f);
		if (num3 <= 0f)
		{
			for (int i = 0; i < _blips.Count; i++)
			{
				_blips[i].SetActive(on: false);
			}
			return;
		}
		Rect rect = _root.rect;
		float width = ((Rect)(ref rect)).width;
		float height = ((Rect)(ref rect)).height;
		int num4 = 0;
		foreach (Sighting sighting in _sightings)
		{
			Vector3 val = (((Object)(object)sighting.Seen != (Object)null) ? sighting.Seen.GetCenterPoint() : sighting.Position);
			float distance = Vector3.Distance(val, position);
			Vector3 val2 = main.WorldToViewportPoint(val);
			HuntMath.Blip blip = HuntMath.Project(val2.x, val2.y, val2.z, width, height, EdgeMargin.Value);
			float num5 = HuntMath.BlipScale(distance, range, FarSize.Value, NearSize.Value);
			float num6 = Opacity.Value * num3 * HuntMath.DistanceFade(distance, range);
			BlipView blipView = ViewAt(num4++);
			blipView.SetActive(on: true);
			blipView.Root.anchoredPosition = new Vector2(blip.X, blip.Y);
			Sprite icon = sighting.Icon;
			bool flag2 = (Object)(object)icon == (Object)null || blip.OffScreen;
			((Component)blipView.Wave).gameObject.SetActive(flag2);
			if (flag2)
			{
				((TMP_Text)blipView.Wave).text = (blip.OffScreen ? EdgeGlyph.Value : Glyph.Value);
				((TMP_Text)blipView.Wave).fontSize = num5;
				((TMP_Text)blipView.Wave).alpha = num6;
				((Transform)((TMP_Text)blipView.Wave).rectTransform).localEulerAngles = (Vector3)(blip.OffScreen ? new Vector3(0f, 0f, blip.Angle) : Vector3.zero);
			}
			((Component)blipView.Icon).gameObject.SetActive((Object)(object)icon != (Object)null);
			if ((Object)(object)icon != (Object)null)
			{
				blipView.Icon.sprite = icon;
				((Graphic)blipView.Icon).color = (sighting.Gold ? new Color(Gold.r, Gold.g, Gold.b, num6) : new Color(1f, 1f, 1f, num6));
				((Graphic)blipView.Icon).rectTransform.sizeDelta = new Vector2(num5 * 1.6f, num5 * 1.6f);
				((Graphic)blipView.Icon).rectTransform.anchoredPosition = new Vector2(0f, flag2 ? (num5 * 1.3f) : 0f);
			}
			string text = num switch
			{
				1 => HuntMath.Ballpark(distance, BallparkStep.Value), 
				0 => "", 
				_ => HuntMath.Exact(distance), 
			};
			((Component)blipView.Label).gameObject.SetActive(text.Length > 0);
			((TMP_Text)blipView.Label).text = text;
			((TMP_Text)blipView.Label).fontSize = num5 * 0.7f;
			((TMP_Text)blipView.Label).alpha = num6;
			((TMP_Text)blipView.Label).rectTransform.anchoredPosition = new Vector2(0f, (0f - num5) * 0.9f);
		}
		for (int j = num4; j < _blips.Count; j++)
		{
			_blips[j].SetActive(on: false);
		}
	}

	private void Sense(Vector3 eye, Vector3 head, Camera cam, float range, int tier)
	{
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: 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)
		//IL_0127: 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_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: 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_0182: Unknown result type (might be due to invalid IL or missing references)
		_sightings.Clear();
		float num = (((Object)(object)EnvMan.instance == (Object)null) ? 0f : HuntMath.Daylight(EnvMan.instance.GetDayFraction()));
		float maxDegrees = MaxBearingError.Value * Mathf.Lerp(1f, DaytimeErrorScale.Value, num);
		float error = HuntMath.ErrorForTier(tier, maxDegrees);
		_scratch.Clear();
		Character.GetCharactersInRange(eye, range, _scratch);
		foreach (Character item in _scratch)
		{
			if (CanSense(item))
			{
				Add(eye, head, cam, error, ((object)item.GetZDOID()/*cast due to .constrained prefix*/).GetHashCode(), item.GetCenterPoint(), item, (tier >= 3) ? SpeciesIcons.For(((Component)item).gameObject, item) : null);
			}
		}
		foreach (IMonoUpdater instance in RandomFlyingBird.Instances)
		{
			RandomFlyingBird val = (RandomFlyingBird)(object)((instance is RandomFlyingBird) ? instance : null);
			if (val == null || !IsGameName(((Component)val).gameObject))
			{
				continue;
			}
			Vector3 position = ((Component)val).transform.position;
			Vector3 val2 = position - eye;
			if (!(((Vector3)(ref val2)).sqrMagnitude > range * range))
			{
				ZNetView component = ((Component)val).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid() && component.GetZDO().GetBool(ZDOVars.s_landed, false))
				{
					Add(eye, head, cam, error, ((Object)val).GetInstanceID(), position, null, (tier >= 3) ? SpeciesIcons.For(((Component)val).gameObject, null) : null);
				}
			}
		}
	}

	private void Add(Vector3 eye, Vector3 head, Camera cam, float error, int seed, Vector3 target, Character live, Sprite icon)
	{
		//IL_0001: 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_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: 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_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = cam.WorldToViewportPoint(target);
		bool flag = HuntMath.InView(val.x, val.y, val.z) && CanSee(head, target, SightRadius.Value);
		if (error > 0f && !flag)
		{
			Quaternion val2 = Quaternion.AngleAxis(HuntMath.BearingErrorDegrees(seed, error), Vector3.up);
			target = eye + val2 * (target - eye);
		}
		_sightings.Add(new Sighting
		{
			Position = target,
			Icon = icon,
			Gold = SpeciesIcons.IsOurs(icon),
			Seen = (flag ? live : null)
		});
	}

	private BlipView ViewAt(int index)
	{
		//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)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		while (_blips.Count <= index)
		{
			GameObject val = new GameObject($"blip{_blips.Count}", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)_root, false);
			RectTransform component = val.GetComponent<RectTransform>();
			Vector2 anchorMin = (component.anchorMax = Vector2.zero);
			component.anchorMin = anchorMin;
			component.pivot = new Vector2(0.5f, 0.5f);
			component.sizeDelta = Vector2.zero;
			_blips.Add(new BlipView
			{
				Root = component,
				Wave = MakeText(component, "wave"),
				Label = MakeText(component, "label"),
				Icon = MakeIcon(component)
			});
		}
		return _blips[index];
	}

	private static TextMeshProUGUI MakeText(RectTransform parent, string name)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: 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)
		GameObject val = new GameObject(name, new Type[2]
		{
			typeof(RectTransform),
			typeof(TextMeshProUGUI)
		});
		val.transform.SetParent((Transform)(object)parent, false);
		TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
		((TMP_Text)component).font = Hud.instance.m_healthText.font;
		((TMP_Text)component).fontSharedMaterial = Hud.instance.m_healthText.fontSharedMaterial;
		((Graphic)component).color = Gold;
		((TMP_Text)component).alignment = (TextAlignmentOptions)514;
		((Graphic)component).raycastTarget = false;
		RectTransform rectTransform = ((TMP_Text)component).rectTransform;
		RectTransform rectTransform2 = ((TMP_Text)component).rectTransform;
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(0.5f, 0.5f);
		rectTransform2.anchorMax = val2;
		rectTransform.anchorMin = val2;
		((TMP_Text)component).rectTransform.pivot = new Vector2(0.5f, 0.5f);
		((TMP_Text)component).rectTransform.sizeDelta = new Vector2(300f, 48f);
		return component;
	}

	private static Image MakeIcon(RectTransform parent)
	{
		//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_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("icon", new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		val.transform.SetParent((Transform)(object)parent, false);
		Image component = val.GetComponent<Image>();
		((Graphic)component).raycastTarget = false;
		component.preserveAspect = true;
		RectTransform rectTransform = ((Graphic)component).rectTransform;
		RectTransform rectTransform2 = ((Graphic)component).rectTransform;
		Vector2 val2 = default(Vector2);
		((Vector2)(ref val2))..ctor(0.5f, 0.5f);
		rectTransform2.anchorMax = val2;
		rectTransform.anchorMin = val2;
		((Graphic)component).rectTransform.pivot = new Vector2(0.5f, 0.5f);
		return component;
	}

	private bool TryCreate()
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Expected O, but got Unknown
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Hud.instance == (Object)null || (Object)(object)Hud.instance.m_rootObject == (Object)null)
		{
			return false;
		}
		GameObject val = new GameObject("SensibleHuntingRoot", new Type[2]
		{
			typeof(RectTransform),
			typeof(Canvas)
		});
		val.transform.SetParent(Hud.instance.m_rootObject.transform, false);
		_root = val.GetComponent<RectTransform>();
		_root.anchorMin = Vector2.zero;
		_root.anchorMax = Vector2.one;
		RectTransform root = _root;
		Vector2 offsetMin = (_root.offsetMax = Vector2.zero);
		root.offsetMin = offsetMin;
		Canvas component = val.GetComponent<Canvas>();
		component.overrideSorting = true;
		component.sortingOrder = 10;
		return true;
	}
}
internal static class SpeciesIcons
{
	private static readonly Dictionary<string, Sprite> Art = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase);

	private static readonly HashSet<Sprite> Ours = new HashSet<Sprite>();

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

	private static readonly Func<Texture2D, byte[], bool> LoadImage = (Func<Texture2D, byte[], bool>)Delegate.CreateDelegate(typeof(Func<Texture2D, byte[], bool>), Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule", throwOnError: true).GetMethod("LoadImage", new Type[2]
	{
		typeof(Texture2D),
		typeof(byte[])
	}));

	internal static string ArtName(string prefab)
	{
		if (string.Equals(prefab, "Chicken", StringComparison.OrdinalIgnoreCase))
		{
			return "Hen";
		}
		int num = prefab.IndexOf('_');
		if (num <= 0)
		{
			return prefab;
		}
		return prefab.Substring(0, num);
	}

	internal static void Load(string dir, ManualLogSource log)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Expected O, but got Unknown
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		if (!Directory.Exists(dir))
		{
			return;
		}
		string[] files = Directory.GetFiles(dir, "*.png");
		foreach (string path in files)
		{
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true)
			{
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)2
			};
			try
			{
				if (!LoadImage(val, File.ReadAllBytes(path)))
				{
					throw new InvalidDataException("not a PNG");
				}
			}
			catch (Exception ex)
			{
				log.LogWarning((object)("Could not load locator art " + fileNameWithoutExtension + ": " + ex.Message));
				Object.Destroy((Object)(object)val);
				continue;
			}
			Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			Art[fileNameWithoutExtension] = val2;
			Ours.Add(val2);
		}
		if (Art.Count > 0)
		{
			log.LogInfo((object)$"Loaded {Art.Count} locator icons");
		}
	}

	internal static Sprite For(GameObject go, Character c)
	{
		string prefabName = Utils.GetPrefabName(go);
		if (Cache.TryGetValue(prefabName, out var value))
		{
			return value;
		}
		if (!Art.TryGetValue(ArtName(prefabName), out var value2) && (Object)(object)c != (Object)null)
		{
			value2 = FromDrops(c);
		}
		Cache[prefabName] = value2;
		return value2;
	}

	internal static bool IsOurs(Sprite s)
	{
		if ((Object)(object)s != (Object)null)
		{
			return Ours.Contains(s);
		}
		return false;
	}

	private static Sprite FromDrops(Character c)
	{
		//IL_0099: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Invalid comparison between Unknown and I4
		Sprite val = null;
		Sprite val2 = null;
		CharacterDrop component = ((Component)c).GetComponent<CharacterDrop>();
		if ((Object)(object)component == (Object)null)
		{
			return null;
		}
		foreach (Drop drop in component.m_drops)
		{
			ItemDrop val3 = (((Object)(object)drop.m_prefab != (Object)null) ? drop.m_prefab.GetComponent<ItemDrop>() : null);
			SharedData val4 = (((Object)(object)val3 != (Object)null) ? val3.m_itemData.m_shared : null);
			if (val4 == null || val4.m_icons == null || val4.m_icons.Length == 0)
			{
				continue;
			}
			Sprite val5 = val4.m_icons[0];
			if (!((Object)(object)val5 == (Object)null))
			{
				if ((int)val4.m_itemType == 13)
				{
					return val5;
				}
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = val5;
				}
			}
		}
		if (!((Object)(object)val != (Object)null))
		{
			return val2;
		}
		return val;
	}
}