Decompiled source of Gnomes v0.7.0

Gnomes.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Logging;
using Bitgem.VFX.StylisedWater;
using Catedral;
using Digger.Modules.Core.Sources;
using Gnomes.Net;
using Gnomes.Server;
using Gnomes.UI;
using Gnomes.World;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using Unity.Collections;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Localization;
using UnityEngine.Localization.Settings;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("Digger.Core")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Gnomes")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A fairy asks the King for help. Bring her gnome hats to summon three gnomes: one collects loot, one takes ore to the Forge, one fetches and opens chests. Plus a weapon shop, harder waves and a King shield. Teams up with SiegeUpgrades and Backpack.")]
[assembly: AssemblyFileVersion("0.7.0.0")]
[assembly: AssemblyInformationalVersion("0.7.0+ac598341b8ee590abdd4d8db4adf0f062d4e13a5")]
[assembly: AssemblyProduct("Gnomes")]
[assembly: AssemblyTitle("Gnomes")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.7.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Gnomes
{
	internal static class BackpackBridge
	{
		private const string ApiTypeName = "Backpack.BackpackApi";

		private const int ApiVersion = 1;

		private const float RetrySeconds = 10f;

		private static bool _ready;

		private static bool _failed;

		private static float _nextTry;

		private static Func<FirstPersonController, List<(int, string, int)>, bool> _hostItems;

		private static Func<FirstPersonController, int, string, int, bool> _hostRemove;

		private static Func<List<(int, string, int)>, bool> _localItems;

		private static float _nextLog;

		public static int LocalVersion { get; private set; }

		public static bool HostReady
		{
			get
			{
				Resolve();
				if (_hostItems != null)
				{
					return _hostRemove != null;
				}
				return false;
			}
		}

		public static bool LocalReady
		{
			get
			{
				Resolve();
				return _localItems != null;
			}
		}

		public static bool TryGetItems(FirstPersonController player, List<(int slot, string itemId, int count)> into)
		{
			if (into == null)
			{
				return false;
			}
			into.Clear();
			Resolve();
			if (_hostItems == null || (Object)(object)player == (Object)null)
			{
				return false;
			}
			try
			{
				return _hostItems(player, into);
			}
			catch (Exception ex)
			{
				into.Clear();
				LogOnce("TryGetItems", ex);
				return false;
			}
		}

		public static bool TryRemove(FirstPersonController player, int slot, string itemId, int count)
		{
			Resolve();
			if (_hostRemove == null || (Object)(object)player == (Object)null || string.IsNullOrEmpty(itemId) || count <= 0)
			{
				return false;
			}
			try
			{
				return _hostRemove(player, slot, itemId, count);
			}
			catch (Exception ex)
			{
				LogOnce("TryRemove", ex);
				return false;
			}
		}

		public static bool TryGetLocalItems(List<(int slot, string itemId, int count)> into)
		{
			if (into == null)
			{
				return false;
			}
			into.Clear();
			Resolve();
			if (_localItems == null)
			{
				return false;
			}
			try
			{
				return _localItems(into);
			}
			catch (Exception ex)
			{
				into.Clear();
				LogOnce("TryGetLocalItems", ex);
				return false;
			}
		}

		private static void Resolve()
		{
			if (_ready || _failed || Time.unscaledTime < _nextTry)
			{
				return;
			}
			_nextTry = Time.unscaledTime + 10f;
			try
			{
				Type type = FindApi();
				if (type == null)
				{
					return;
				}
				FieldInfo field = type.GetField("Version", BindingFlags.Static | BindingFlags.Public);
				object obj = ((field != null && field.FieldType == typeof(int)) ? field.GetValue(null) : null);
				if (!(obj is int num) || num != 1)
				{
					_failed = true;
					Plugin.Log.LogWarning((object)($"Gnomes: o Backpack instalado tem outra versão da API ({obj}, esperada {1}); " + "a fada não vende as armas da mochila."));
					return;
				}
				_hostItems = Bind<Func<FirstPersonController, List<(int, string, int)>, bool>>(type, "TryGetItems", new Type[2]
				{
					typeof(FirstPersonController),
					typeof(List<(int, string, int)>)
				});
				_hostRemove = Bind<Func<FirstPersonController, int, string, int, bool>>(type, "TryRemove", new Type[4]
				{
					typeof(FirstPersonController),
					typeof(int),
					typeof(string),
					typeof(int)
				});
				_localItems = Bind<Func<List<(int, string, int)>, bool>>(type, "TryGetLocalItems", new Type[1] { typeof(List<(int, string, int)>) });
				if (_hostItems == null || _hostRemove == null || _localItems == null)
				{
					_hostItems = null;
					_hostRemove = null;
					_localItems = null;
					_failed = true;
					Plugin.Log.LogWarning((object)"Gnomes: o Backpack instalado tem a API com outro formato; a fada não vende as armas da mochila.");
					return;
				}
				EventInfo eventInfo = type.GetEvent("LocalChanged", BindingFlags.Static | BindingFlags.Public);
				if (eventInfo != null && eventInfo.EventHandlerType == typeof(Action))
				{
					eventInfo.AddEventHandler(null, new Action(OnLocalChanged));
				}
				_ready = true;
				Plugin.Log.LogInfo((object)"Gnomes: mochila do Backpack encontrada; a fada compra as armas guardadas nela.");
			}
			catch (Exception ex)
			{
				_failed = true;
				Plugin.Log.LogWarning((object)("Gnomes: não deu para usar a mochila do Backpack: " + ex.Message));
			}
		}

		private static Type FindApi()
		{
			Assembly assembly = typeof(BackpackBridge).Assembly;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly2 in assemblies)
			{
				if (!(assembly2 == assembly))
				{
					Type type;
					try
					{
						type = assembly2.GetType("Backpack.BackpackApi", throwOnError: false);
					}
					catch
					{
						continue;
					}
					if (type != null)
					{
						return type;
					}
				}
			}
			return null;
		}

		private static T Bind<T>(Type api, string name, params Type[] parameters) where T : Delegate
		{
			MethodInfo method = api.GetMethod(name, BindingFlags.Static | BindingFlags.Public, null, parameters, null);
			if (method == null || method.ReturnType != typeof(bool))
			{
				return null;
			}
			try
			{
				return (T)method.CreateDelegate(typeof(T));
			}
			catch
			{
				return null;
			}
		}

		private static void OnLocalChanged()
		{
			try
			{
				LocalVersion++;
			}
			catch (Exception ex)
			{
				LogOnce("LocalChanged", ex);
			}
		}

		private static void LogOnce(string what, Exception ex)
		{
			if (!(Time.unscaledTime < _nextLog))
			{
				_nextLog = Time.unscaledTime + 10f;
				Plugin.Log.LogWarning((object)("Gnomes: erro na mochila do Backpack (" + what + "): " + ex.Message));
			}
		}
	}
	[BepInPlugin("catedralemchamas.stonewards.gnomes", "Gnomes", "0.7.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static readonly float MoveSpeed = 4f;

		internal static readonly int CarryBaseSlots = 3;

		internal static readonly int CarrySlotEveryLevels = 5;

		internal static readonly int CarrySlotsPerStep = 2;

		internal static readonly int CarryMaxSlots = 16;

		internal static readonly float CarryStackMultiplier = 2f;

		internal static readonly float LingerSeconds = 3f;

		internal static readonly float GnomeSightRadius = 5f;

		internal static readonly float PlayerSafeRadius = 3f;

		internal static readonly float PlayerSafeSeconds = 1.5f;

		internal static readonly float ItemMinAgeSeconds = 1f;

		internal static readonly float CollectRadius = 1.3f;

		internal static readonly float JumpGrabHeight = 3.2f;

		internal static readonly float UnreachableRetrySeconds = 20f;

		internal static readonly float UnreachableRetryMaxSeconds = 180f;

		internal static readonly float PathCheckBudgetMs = 2.5f;

		internal static readonly float NearCheckRadius = 9f;

		internal static readonly bool FollowMinersWhenIdle = true;

		internal static readonly float StuckTeleportSeconds = 4f;

		internal static readonly float HomeOffsetX = 6f;

		internal static readonly float HomeOffsetZ = 7f;

		internal static readonly float DiscoverRadius = 25f;

		internal static readonly Rarity[] WakeWeaponRarityByDifficulty;

		internal static readonly int XpBase;

		internal static readonly int XpPerLevel;

		internal static readonly int[] CollectorXpTenthsPerOreByRarity;

		internal static readonly int[] CollectorXpPerWeaponByRarity;

		internal static readonly int WaveXpPerGnome;

		internal static readonly float ExtraLevelDamagePercent;

		internal static readonly float ExtraLevelHealthPercent;

		internal static readonly int CandyPerWaveBase;

		internal static readonly int CandyPerWave;

		internal static readonly (int Min, int Max)[] CandyChestRanges;

		internal static readonly (int Level, int Candies)[] CandyForgeLevelTiers;

		internal static readonly int[] WeaponCandiesByRarity;

		internal static readonly int[] CollectorCostByDifficulty;

		internal static readonly int[] SellerCostByDifficulty;

		internal static readonly int[] ChestRunnerCostByDifficulty;

		internal static readonly int ExtraGnomeStartLevel;

		internal static readonly int LevelSpeedBaseLevel;

		internal const string VoxelShader = "";

		internal static readonly bool FairyFireflies;

		internal static readonly int FairyFireflyCount;

		internal static readonly bool FairyGarden;

		internal static readonly int FairyGardenCount;

		internal static readonly int StashStackSize;

		internal static readonly (int Kills, int Slots)[] StashTiers;

		internal static readonly bool StashDiscardNotice;

		internal static readonly bool DebugStartWithAllGnomes;

		internal static readonly int DebugStartCandies;

		internal static readonly int DebugStartLevel;

		internal static readonly bool DebugStartUnlocked;

		internal static readonly int DebugHatDropChancePercent;

		internal static readonly int DebugFairyStartLevel;

		internal static readonly bool VerboseLog;

		internal static readonly float CollectorDiagnosticSeconds;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			GnomeFilters.Init();
			GnomeNet.RegisterSerializers();
			_harmony = new Harmony("catedralemchamas.stonewards.gnomes");
			_harmony.PatchAll();
			((Component)this).gameObject.AddComponent<GnomeDirector>();
			((Component)this).gameObject.AddComponent<StashWindow>();
			((Component)this).gameObject.AddComponent<ShopWindow>();
			((Component)this).gameObject.AddComponent<GnomeHud>();
			((Component)this).gameObject.AddComponent<DialogWindow>();
			((Component)this).gameObject.AddComponent<InputGuard>();
			((Component)this).gameObject.AddComponent<HudCandyCounter>();
			((Component)this).gameObject.AddComponent<GnomeMarkers>();
			((Component)this).gameObject.AddComponent<FairyQuest>();
			((Component)this).gameObject.AddComponent<GnomeLevelFx>();
			((Component)this).gameObject.AddComponent<GnomeSummonFx>();
			((Component)this).gameObject.AddComponent<GnomeHornFx>();
			((Component)this).gameObject.AddComponent<GnomeFuryFx>();
			((Component)this).gameObject.AddComponent<KingShieldFx>();
			((Component)this).gameObject.AddComponent<FairyFireflies>();
			((Component)this).gameObject.AddComponent<FairyGarden>();
			((Component)this).gameObject.AddComponent<MossCarpet>();
			((Component)this).gameObject.AddComponent<CarriedChestVisual>();
			((Component)this).gameObject.AddComponent<GnomePotionVisual>();
			((Component)this).gameObject.AddComponent<GnomeCombatFx>();
			((Component)this).gameObject.AddComponent<GnomeDigFx>();
			((Component)this).gameObject.AddComponent<PlayerPassThrough>();
			Log.LogInfo((object)"Gnomes v0.7.0 carregado. Todos os jogadores precisam ter o mod.");
		}

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

		static Plugin()
		{
			Rarity[] array = new Rarity[3];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			WakeWeaponRarityByDifficulty = (Rarity[])(object)array;
			XpBase = 30;
			XpPerLevel = 6;
			CollectorXpTenthsPerOreByRarity = new int[5] { 12, 20, 40, 80, 160 };
			CollectorXpPerWeaponByRarity = new int[5] { 2, 3, 5, 20, 100 };
			WaveXpPerGnome = 50;
			ExtraLevelDamagePercent = 1f;
			ExtraLevelHealthPercent = 1f;
			CandyPerWaveBase = 20;
			CandyPerWave = 5;
			CandyChestRanges = new(int, int)[5]
			{
				(1, 5),
				(5, 10),
				(10, 15),
				(15, 20),
				(20, 25)
			};
			CandyForgeLevelTiers = new(int, int)[6]
			{
				(1, 5),
				(10, 10),
				(20, 15),
				(30, 20),
				(40, 25),
				(50, 30)
			};
			WeaponCandiesByRarity = new int[5] { 5, 10, 20, 40, 80 };
			CollectorCostByDifficulty = new int[3] { 150, 225, 300 };
			SellerCostByDifficulty = new int[3] { 150, 225, 300 };
			ChestRunnerCostByDifficulty = new int[3] { 150, 225, 300 };
			ExtraGnomeStartLevel = 1;
			LevelSpeedBaseLevel = 10;
			FairyFireflies = true;
			FairyFireflyCount = 8;
			FairyGarden = true;
			FairyGardenCount = 10;
			StashStackSize = 99;
			StashTiers = new(int, int)[7]
			{
				(0, 10),
				(100, 20),
				(200, 30),
				(400, 40),
				(600, 50),
				(800, 60),
				(1000, 80)
			};
			StashDiscardNotice = true;
			DebugStartWithAllGnomes = false;
			DebugStartCandies = 0;
			DebugStartLevel = 1;
			DebugStartUnlocked = false;
			DebugHatDropChancePercent = -1;
			DebugFairyStartLevel = -1;
			VerboseLog = false;
			CollectorDiagnosticSeconds = 5f;
		}
	}
	internal static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "catedralemchamas.stonewards.gnomes";

		public const string PLUGIN_NAME = "Gnomes";

		public const string PLUGIN_VERSION = "0.7.0";

		public const string PLUGIN_AUTHOR = "CatedralEmChamas";
	}
}
namespace Gnomes.World
{
	internal class CarriedChestVisual : MonoBehaviour
	{
		private sealed class Visual
		{
			public GnomeEntity Entity;

			public Transform Root;

			public readonly List<GameObject> Pieces = new List<GameObject>();

			public readonly List<Renderer> Renderers = new List<Renderer>();

			public string Ids;

			public float Pile;

			public float RetryAt;

			public bool Shown;

			public float Top => HeightFor(Entity) + Pile;
		}

		private const string ChildName = "Gnomes_CarriedChest";

		private const float VoxelScale = 0.55f;

		private const float MiniatureWidth = 0.46f;

		private const float MiniatureMaxHeight = 0.42f;

		private const float RetrySeconds = 2f;

		private const float MaxPileHeight = 0.62f;

		private const int MaxPieces = 8;

		private readonly Dictionary<int, Visual> _visuals = new Dictionary<int, Visual>();

		private readonly List<int> _dead = new List<int>();

		private static readonly Dictionary<string, GameObject> Templates = new Dictionary<string, GameObject>();

		private static readonly Dictionary<string, Vector3> TemplateSizes = new Dictionary<string, Vector3>();

		private static GameObject _voxelTemplate;

		private static Vector3 _voxelSize;

		private static Transform _storage;

		private static readonly List<string> IdParts = new List<string>();

		private static readonly List<GameObject> PieceTemplates = new List<GameObject>();

		private static readonly List<Vector3> PieceSizes = new List<Vector3>();

		private static Transform Storage
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Expected O, but got Unknown
				if ((Object)(object)_storage == (Object)null)
				{
					GameObject val = new GameObject("Gnomes_ChestMiniatures");
					val.SetActive(false);
					Object.DontDestroyOnLoad((Object)val);
					_storage = val.transform;
				}
				return _storage;
			}
		}

		private static GameObject VoxelTemplate
		{
			get
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Expected O, but got Unknown
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Expected O, but got Unknown
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//IL_008e: 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_00b9: 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_0121: Unknown result type (might be due to invalid IL or missing references)
				//IL_0126: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)_voxelTemplate != (Object)null)
				{
					return _voxelTemplate;
				}
				GameObject val = new GameObject("Gnomes_ChestMini_Voxel");
				val.transform.SetParent(Storage, false);
				GameObject val2 = new GameObject("Voxel");
				val2.transform.SetParent(val.transform, false);
				val2.transform.localScale = Vector3.one * 0.55f;
				float num = 0.07f;
				VoxelLibrary.GetWoodChest(out var mesh, out var material);
				CreateModel(val2.transform, mesh, material);
				GameObject val3 = new GameObject("LidHinge");
				val3.transform.SetParent(val2.transform, false);
				val3.transform.localPosition = new Vector3(0f, 10f * num, 5.5f * num);
				VoxelLibrary.GetWoodChestLid(out var mesh2, out var material2);
				((Component)CreateModel(val3.transform, mesh2, material2)).transform.localPosition = new Vector3(0f, 0f, -5.5f * num);
				_voxelSize = new Vector3(16f * num * 0.55f, 16f * num * 0.55f, 11f * num * 0.55f);
				_voxelTemplate = val;
				return val;
			}
		}

		private static float HeightFor(GnomeEntity entity)
		{
			return VoxelLibrary.GnomeHeadLoadY((!((Object)(object)entity != (Object)null) || entity.Stage <= 0) ? 1 : entity.Stage);
		}

		private void LateUpdate()
		{
			try
			{
				Tick();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Gnomes: erro no visual do baú carregado: " + ex.Message));
			}
		}

		private void Tick()
		{
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			_dead.Clear();
			foreach (KeyValuePair<int, Visual> visual in _visuals)
			{
				if ((Object)(object)visual.Value.Entity == (Object)null || (Object)(object)visual.Value.Root == (Object)null)
				{
					_dead.Add(visual.Key);
				}
			}
			foreach (int item in _dead)
			{
				_visuals.Remove(item);
			}
			foreach (GnomeEntity item2 in GnomeEntity.All)
			{
				if ((Object)(object)item2 == (Object)null)
				{
					continue;
				}
				_visuals.TryGetValue(((Object)item2).GetInstanceID(), out var value);
				GnomeStateMsg state;
				bool num = item2.TryGetState(out state);
				bool flag = num && item2.Kind == GnomeKind.ChestRunner && !string.IsNullOrEmpty(state.CarriedItemId);
				if (!num || (state.State != GnomeState.CarryingChest && state.State != GnomeState.WaitingChest && !(state.State == GnomeState.FetchingChest && flag) && (state.State != GnomeState.DrinkingPotion || value == null || !value.Shown) && (state.State != GnomeState.BlowingHorn || value == null || !value.Shown)))
				{
					if (value != null)
					{
						SetVisible(value, on: false);
					}
					continue;
				}
				if (value == null)
				{
					value = Create(item2);
					if (value == null)
					{
						continue;
					}
					_visuals[((Object)item2).GetInstanceID()] = value;
				}
				string text = (flag ? state.CarriedItemId : (value.Ids ?? ""));
				if (value.Pieces.Count == 0 || !string.Equals(text, value.Ids, StringComparison.Ordinal) || (value.RetryAt > 0f && Time.unscaledTime >= value.RetryAt))
				{
					Rebuild(value, text);
				}
				float num2 = Mathf.Sin(Time.time * 6f + (float)((Object)item2).GetInstanceID()) * 0.03f;
				value.Root.localPosition = new Vector3(0f, HeightFor(item2) + num2, 0f);
				SetVisible(value, on: true);
			}
		}

		private static void SetVisible(Visual v, bool on)
		{
			v.Shown = on;
			if ((Object)(object)v.Root != (Object)null && ((Component)v.Root).gameObject.activeSelf != on)
			{
				((Component)v.Root).gameObject.SetActive(on);
			}
			if ((Object)(object)v.Entity != (Object)null)
			{
				v.Entity.HeadLoadTop = (on ? v.Top : 0f);
			}
			for (int i = 0; i < v.Renderers.Count; i++)
			{
				if ((Object)(object)v.Renderers[i] != (Object)null)
				{
					v.Renderers[i].enabled = on;
				}
			}
		}

		private static Visual Create(GnomeEntity entity)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			Transform val = (((Object)(object)entity.Standing != (Object)null) ? entity.Standing : ((Component)entity).transform);
			Transform val2 = val.Find("Gnomes_CarriedChest");
			if ((Object)(object)val2 != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val2).gameObject);
			}
			GameObject val3 = new GameObject("Gnomes_CarriedChest");
			val3.transform.SetParent(val, false);
			val3.transform.localPosition = new Vector3(0f, HeightFor(entity), 0f);
			val3.transform.localRotation = Quaternion.identity;
			val3.transform.localScale = Vector3.one;
			return new Visual
			{
				Entity = entity,
				Root = val3.transform
			};
		}

		private static void Rebuild(Visual v, string ids)
		{
			//IL_0172: 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_018a: Unknown result type (might be due to invalid IL or missing references)
			foreach (GameObject piece in v.Pieces)
			{
				if (!((Object)(object)piece == (Object)null))
				{
					piece.SetActive(false);
					Object.Destroy((Object)(object)piece);
				}
			}
			v.Pieces.Clear();
			v.Renderers.Clear();
			v.Ids = ids;
			v.RetryAt = 0f;
			IdParts.Clear();
			if (!string.IsNullOrEmpty(ids))
			{
				int num = 0;
				for (int i = 0; i <= ids.Length; i++)
				{
					if (IdParts.Count >= 8)
					{
						break;
					}
					if (i >= ids.Length || ids[i] == ',')
					{
						if (i > num)
						{
							IdParts.Add(ids.Substring(num, i - num).Trim());
						}
						num = i + 1;
					}
				}
			}
			if (IdParts.Count == 0)
			{
				IdParts.Add(null);
			}
			PieceTemplates.Clear();
			PieceSizes.Clear();
			foreach (string idPart in IdParts)
			{
				bool retry = false;
				GameObject val = (string.IsNullOrEmpty(idPart) ? null : GetTemplate(idPart, out retry));
				if ((Object)(object)val == (Object)null && retry)
				{
					v.RetryAt = Time.unscaledTime + 2f;
				}
				if ((Object)(object)val == (Object)null || !TemplateSizes.TryGetValue(idPart, out var value))
				{
					val = VoxelTemplate;
					value = _voxelSize;
				}
				PieceTemplates.Add(val);
				PieceSizes.Add(value);
			}
			Layout(v);
		}

		private static void Layout(Visual v)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: 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_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: 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)
			int count = PieceTemplates.Count;
			float num = count switch
			{
				2 => 0.8f, 
				1 => 1f, 
				_ => 0.62f, 
			};
			float num2 = 0f;
			if (count <= 2)
			{
				for (int i = 0; i < count; i++)
				{
					num2 += PieceSizes[i].y;
				}
			}
			else
			{
				for (int j = 0; j * 2 < count; j++)
				{
					float num3 = PieceSizes[j * 2].y;
					if (j * 2 + 1 < count)
					{
						num3 = Mathf.Max(num3, PieceSizes[j * 2 + 1].y);
					}
					num2 += num3;
				}
			}
			if (count > 1 && num2 * num > 0.62f)
			{
				num = 0.62f / Mathf.Max(0.01f, num2);
			}
			float num4 = 0f;
			Vector3 localPosition = default(Vector3);
			for (int k = 0; k < count; k++)
			{
				Vector3 val = PieceSizes[k];
				Quaternion localRotation;
				if (count <= 2)
				{
					((Vector3)(ref localPosition))..ctor(0f, num4, 0f);
					localRotation = Quaternion.Euler(0f, (k == 0) ? 0f : 12f, 0f);
					num4 += val.y * num;
				}
				else
				{
					int num5 = k / 2;
					bool flag = num5 * 2 + 1 < count;
					bool flag2 = num5 % 2 == 0;
					float num6 = (flag ? (val.x * num * 0.5f + 0.01f) : 0f);
					float num7 = ((!flag) ? 0f : ((k % 2 == 0) ? (0f - num6) : num6));
					localPosition = (flag2 ? new Vector3(num7, num4, 0f) : new Vector3(0f, num4, num7));
					localRotation = Quaternion.Euler(0f, flag2 ? 0f : 90f, 0f);
					if (k % 2 == 1 || !flag)
					{
						float num8 = PieceSizes[k].y;
						if (flag)
						{
							num8 = Mathf.Max(num8, PieceSizes[k - 1].y);
						}
						num4 += num8 * num;
					}
				}
				GameObject val2 = Object.Instantiate<GameObject>(PieceTemplates[k], v.Root, false);
				((Object)val2).name = "Chest" + k;
				val2.SetActive(true);
				val2.transform.localPosition = localPosition;
				val2.transform.localRotation = localRotation;
				val2.transform.localScale = Vector3.one * num;
				v.Pieces.Add(val2);
				v.Renderers.AddRange(val2.GetComponentsInChildren<Renderer>(true));
			}
			v.Pile = Mathf.Max(num4, 0.05f);
		}

		private static MeshRenderer CreateModel(Transform parent, Mesh mesh, Material material)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Model");
			val.transform.SetParent(parent, false);
			val.AddComponent<MeshFilter>().sharedMesh = mesh;
			MeshRenderer obj = val.AddComponent<MeshRenderer>();
			((Renderer)obj).sharedMaterial = material;
			return obj;
		}

		private static GameObject GetTemplate(string chestId, out bool retry)
		{
			retry = false;
			if (Templates.TryGetValue(chestId, out var value))
			{
				if ((Object)(object)value != (Object)null)
				{
					return value;
				}
				if (value == null)
				{
					return null;
				}
			}
			ItemManager instance = ItemManager.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				retry = true;
				return null;
			}
			GameObject val = null;
			string text = null;
			try
			{
				CarriableDataSO carriableDataSoByID = instance.GetCarriableDataSoByID(chestId);
				if ((Object)(object)carriableDataSoByID == (Object)null)
				{
					text = "id não existe no banco de baús do jogo";
				}
				else
				{
					if ((Object)(object)carriableDataSoByID.CarriableObjectPrefab != (Object)null)
					{
						val = Build(chestId, ((Component)carriableDataSoByID.CarriableObjectPrefab).gameObject);
					}
					if ((Object)(object)val == (Object)null && (Object)(object)carriableDataSoByID.CarriedObjectPrefab != (Object)null)
					{
						val = Build(chestId, ((Component)carriableDataSoByID.CarriedObjectPrefab).gameObject);
					}
					if ((Object)(object)val == (Object)null)
					{
						text = "o baú não tem malhas visíveis";
					}
				}
			}
			catch (Exception ex)
			{
				text = ex.GetType().Name + ": " + ex.Message;
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
					val = null;
				}
			}
			Templates[chestId] = val;
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("Gnomes: miniatura do baú " + chestId + " indisponível (" + text + "); usando o baú de voxels na cabeça do Caçador."));
			}
			return val;
		}

		private static GameObject Build(string chestId, GameObject source)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Gnomes_ChestMini_" + chestId);
			val.transform.SetParent(Storage, false);
			List<MeshFilter> list = new List<MeshFilter>();
			int skinned = 0;
			Transform val2 = WeaponVisuals.CopyRenderers(source.transform, val.transform, isRoot: true, LodSkipSet(source), list, ref skinned);
			if (list.Count == 0)
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			Matrix4x4 worldToLocalMatrix = val2.worldToLocalMatrix;
			Bounds val3 = WeaponVisuals.MeshBounds(list[0], worldToLocalMatrix);
			for (int i = 1; i < list.Count; i++)
			{
				((Bounds)(ref val3)).Encapsulate(WeaponVisuals.MeshBounds(list[i], worldToLocalMatrix));
			}
			float num = Mathf.Max(((Bounds)(ref val3)).size.x, ((Bounds)(ref val3)).size.z);
			if (num < 0.001f || ((Bounds)(ref val3)).size.y < 0.001f)
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			float num2 = Mathf.Min(0.46f / num, 0.42f / ((Bounds)(ref val3)).size.y);
			Quaternion val4 = Quaternion.Euler(0f, 180f, 0f);
			Vector3 val5 = default(Vector3);
			((Vector3)(ref val5))..ctor(((Bounds)(ref val3)).center.x, ((Bounds)(ref val3)).min.y, ((Bounds)(ref val3)).center.z);
			val2.localRotation = val4;
			val2.localScale = Vector3.one * num2;
			val2.localPosition = -(val4 * (val5 * num2));
			TemplateSizes[chestId] = new Vector3(((Bounds)(ref val3)).size.x * num2, ((Bounds)(ref val3)).size.y * num2, ((Bounds)(ref val3)).size.z * num2);
			if (Plugin.VerboseLog)
			{
				Plugin.Log.LogInfo((object)($"Gnomes: miniatura do baú {chestId} montada de '{((Object)source).name}': {list.Count} malhas ({skinned} de esqueleto), " + $"caixa {((Bounds)(ref val3)).size.x:0.##}x{((Bounds)(ref val3)).size.y:0.##}x{((Bounds)(ref val3)).size.z:0.##} m, escala {num2:0.###}."));
			}
			return val;
		}

		private static HashSet<Renderer> LodSkipSet(GameObject source)
		{
			HashSet<Renderer> hashSet = new HashSet<Renderer>();
			LODGroup[] componentsInChildren = source.GetComponentsInChildren<LODGroup>(true);
			foreach (LODGroup val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || !val.enabled)
				{
					continue;
				}
				LOD[] lODs = val.GetLODs();
				if (lODs == null || lODs.Length < 2)
				{
					continue;
				}
				int num = -1;
				Renderer[] renderers;
				for (int j = 0; j < lODs.Length; j++)
				{
					if (num >= 0)
					{
						break;
					}
					if (lODs[j].renderers == null)
					{
						continue;
					}
					renderers = lODs[j].renderers;
					for (int k = 0; k < renderers.Length; k++)
					{
						if ((Object)(object)renderers[k] != (Object)null)
						{
							num = j;
							break;
						}
					}
				}
				if (num < 0)
				{
					continue;
				}
				HashSet<Renderer> hashSet2 = new HashSet<Renderer>();
				renderers = lODs[num].renderers;
				foreach (Renderer val2 in renderers)
				{
					if ((Object)(object)val2 != (Object)null)
					{
						hashSet2.Add(val2);
					}
				}
				for (int l = 0; l < lODs.Length; l++)
				{
					if (l == num || lODs[l].renderers == null)
					{
						continue;
					}
					renderers = lODs[l].renderers;
					foreach (Renderer val3 in renderers)
					{
						if ((Object)(object)val3 != (Object)null && !hashSet2.Contains(val3))
						{
							hashSet.Add(val3);
						}
					}
				}
			}
			return hashSet;
		}
	}
	[HarmonyPatch(typeof(PlayerInteraction), "RaycastForTarget")]
	internal static class FairyAimPatch
	{
		private static float _nextErrorLog;

		private static bool Prepare()
		{
			if (AccessTools.DeclaredMethod(typeof(PlayerInteraction), "RaycastForTarget", Type.EmptyTypes, (Type[])null)?.ReturnType == typeof(ICrosshairTarget) && AccessTools.DeclaredField(typeof(PlayerInteraction), "raycastSource")?.FieldType == typeof(Transform) && AccessTools.DeclaredField(typeof(PlayerInteraction), "fpsSettingsSO")?.FieldType == typeof(FPSSettingsSO) && AccessTools.DeclaredField(typeof(FPSSettingsSO), "interactorLayerMask")?.FieldType == typeof(LayerMask))
			{
				return true;
			}
			Plugin.Log.LogWarning((object)"Gnomes: PlayerInteraction mudou; não dá para mirar na fada dos gnomos.");
			return false;
		}

		private static void Postfix(ref ICrosshairTarget __result, Transform ___raycastSource, FPSSettingsSO ___fpsSettingsSO)
		{
			//IL_0035: 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_005e: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				FairyEntity current = FairyEntity.Current;
				if (((Object)(object)current == (Object)null && HatEntity.All.Count == 0) || (Object)(object)___raycastSource == (Object)null || (Object)(object)___fpsSettingsSO == (Object)null)
				{
					return;
				}
				Ray val = default(Ray);
				((Ray)(ref val))..ctor(___raycastSource.position, ___raycastSource.forward);
				ICrosshairTarget val2 = null;
				float num = float.MaxValue;
				float num2 = 0f;
				if ((Object)(object)current != (Object)null && current.AimHit(val, current.GetInteractionDistance(), out var distance))
				{
					val2 = (ICrosshairTarget)(object)current;
					num = (num2 = distance);
				}
				for (int i = 0; i < HatEntity.All.Count; i++)
				{
					HatEntity hatEntity = HatEntity.All[i];
					if ((Object)(object)hatEntity != (Object)null && hatEntity.AimHit(val, hatEntity.GetInteractionDistance(), out var distance2) && distance2 < num)
					{
						val2 = (ICrosshairTarget)(object)hatEntity;
						num = distance2;
						num2 = Mathf.Max(distance2, Vector3.Dot(hatEntity.Center - ((Ray)(ref val)).origin, ((Ray)(ref val)).direction));
					}
				}
				RaycastHit val3 = default(RaycastHit);
				if (val2 != null && !Physics.Raycast(val, ref val3, num2, LayerMask.op_Implicit(___fpsSettingsSO.interactorLayerMask)))
				{
					__result = val2;
				}
			}
			catch (Exception arg)
			{
				if (Time.unscaledTime >= _nextErrorLog)
				{
					_nextErrorLog = Time.unscaledTime + 10f;
					Plugin.Log.LogError((object)$"Gnomes: erro na mira da fada: {arg}");
				}
			}
		}
	}
	internal sealed class FairyAura
	{
		private const float Push = 0.35f;

		private const float OuterBehind = 0.02f;

		private static readonly Vector2 InnerSize = new Vector2(2.3f, 2.8f);

		private static readonly Vector2 OuterSize = new Vector2(3.6f, 4.3f);

		private static readonly Color InnerColor = new Color(1f, 0.9f, 0.58f, 1f);

		private static readonly Color OuterColor = new Color(0.9f, 0.97f, 0.86f, 1f);

		private const float Falloff = 3.2f;

		private const int TextureSize = 64;

		private static Sprite _sprite;

		private static Material _material;

		private static bool _assetsTried;

		private readonly GameObject _root;

		private readonly Transform _innerT;

		private readonly Transform _outerT;

		private readonly SpriteRenderer _inner;

		private readonly SpriteRenderer _outer;

		private bool _shown = true;

		public bool Alive => (Object)(object)_root != (Object)null;

		private FairyAura(GameObject root, SpriteRenderer inner, SpriteRenderer outer)
		{
			_root = root;
			_inner = inner;
			_outer = outer;
			_innerT = ((Component)inner).transform;
			_outerT = ((Component)outer).transform;
		}

		public static FairyAura Create()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			GameObject val = new GameObject("Gnomes_FairyAura");
			SpriteRenderer val2 = AddPlate(val.transform, "Outer");
			SpriteRenderer val3 = AddPlate(val.transform, "Inner");
			if (!EnsureAssets(val3))
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			Sprite sprite = (val2.sprite = _sprite);
			val3.sprite = sprite;
			Material sharedMaterial = (((Renderer)val2).sharedMaterial = _material);
			((Renderer)val3).sharedMaterial = sharedMaterial;
			FairyAura fairyAura = new FairyAura(val, val3, val2);
			fairyAura.Hide();
			return fairyAura;
		}

		private static SpriteRenderer AddPlate(Transform parent, string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			SpriteRenderer obj = val.AddComponent<SpriteRenderer>();
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			((Renderer)obj).lightProbeUsage = (LightProbeUsage)0;
			((Renderer)obj).reflectionProbeUsage = (ReflectionProbeUsage)0;
			return obj;
		}

		public void Tick(Camera cam, Vector3 body, float charge, float burst, bool highlighted, float now)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: 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_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)cam).transform;
			Vector3 position = transform.position;
			Vector3 val = body - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			float num = Smooth(0.9f, 2.4f, magnitude) * Fog(magnitude);
			float detailDistance = FairyConfig.DetailDistance;
			if (detailDistance > 0f)
			{
				num *= 1f - Smooth(detailDistance * 0.65f, detailDistance * 0.88f, magnitude);
			}
			if (num <= 0.002f)
			{
				Hide();
				return;
			}
			float num2 = 0.36f * (1f + Mathf.Sin(now * 1.9f) * 0.14f) + charge * 0.3f + burst * 0.45f + (highlighted ? 0.06f : 0f);
			float num3 = 0.15f * (1f + Mathf.Sin(now * 1.25f + 1.3f) * 0.18f) + charge * 0.18f + burst * 0.35f;
			float num4 = 1f + charge * 0.18f + burst * 0.45f;
			float num5 = 1f + charge * 0.3f + burst * 0.7f;
			Vector3 val2 = ((magnitude > 0.01f) ? (val / magnitude) : transform.forward);
			Quaternion rotation = transform.rotation;
			_innerT.SetPositionAndRotation(body + val2 * 0.35f, rotation);
			_innerT.localScale = new Vector3(InnerSize.x * num4, InnerSize.y * num4, 1f);
			_outerT.SetPositionAndRotation(body + val2 * 0.37f, rotation);
			_outerT.localScale = new Vector3(OuterSize.x * num5, OuterSize.y * num5, 1f);
			Color innerColor = InnerColor;
			innerColor.a = Mathf.Clamp01(num2 * num);
			_inner.color = innerColor;
			innerColor = OuterColor;
			innerColor.a = Mathf.Clamp01(num3 * num);
			_outer.color = innerColor;
			_shown = true;
			if (!((Renderer)_inner).enabled)
			{
				((Renderer)_inner).enabled = true;
			}
			if (!((Renderer)_outer).enabled)
			{
				((Renderer)_outer).enabled = true;
			}
		}

		public void Hide()
		{
			if (_shown)
			{
				_shown = false;
				if ((Object)(object)_inner != (Object)null)
				{
					((Renderer)_inner).enabled = false;
				}
				if ((Object)(object)_outer != (Object)null)
				{
					((Renderer)_outer).enabled = false;
				}
			}
		}

		public void Destroy()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
		}

		private static float Smooth(float from, float to, float x)
		{
			float num = Mathf.Clamp01((x - from) / (to - from));
			return num * num * (3f - 2f * num);
		}

		internal static float Fog(float distance)
		{
			//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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			if (!RenderSettings.fog)
			{
				return 1f;
			}
			FogMode fogMode = RenderSettings.fogMode;
			if ((int)fogMode != 1)
			{
				if ((int)fogMode == 2)
				{
					return Mathf.Exp((0f - RenderSettings.fogDensity) * distance);
				}
				float num = RenderSettings.fogDensity * distance;
				return Mathf.Exp((0f - num) * num);
			}
			float fogStartDistance = RenderSettings.fogStartDistance;
			float fogEndDistance = RenderSettings.fogEndDistance;
			if (!(fogEndDistance > fogStartDistance))
			{
				return 1f;
			}
			return Mathf.Clamp01((fogEndDistance - distance) / (fogEndDistance - fogStartDistance));
		}

		private static bool EnsureAssets(SpriteRenderer probe)
		{
			//IL_0086: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			if (_assetsTried)
			{
				if ((Object)(object)_sprite != (Object)null)
				{
					return (Object)(object)_material != (Object)null;
				}
				return false;
			}
			_assetsTried = true;
			Material sharedMaterial = ((Renderer)probe).sharedMaterial;
			if ((Object)(object)sharedMaterial != (Object)null && (Object)(object)sharedMaterial.shader != (Object)null && sharedMaterial.shader.isSupported)
			{
				_material = sharedMaterial;
			}
			else
			{
				Shader val = Shader.Find("Sprites/Default") ?? Shader.Find("Universal Render Pipeline/2D/Sprite-Unlit-Default");
				if ((Object)(object)val != (Object)null && val.isSupported)
				{
					_material = new Material(val)
					{
						name = "Gnomes_FairyAuraMaterial",
						hideFlags = (HideFlags)61
					};
				}
			}
			if ((Object)(object)_material == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Gnomes: sem material de sprite para a aura da fada (ela fica sem aura).");
				return false;
			}
			_sprite = BuildSprite();
			return (Object)(object)_sprite != (Object)null;
		}

		private static Sprite BuildSprite()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_011f: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false)
			{
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61,
				name = "Gnomes_FairyAuraTexture"
			};
			Color32[] array = (Color32[])(object)new Color32[4096];
			float num = 32f;
			float num2 = Mathf.Exp(-3.2f);
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num3 = ((float)j + 0.5f - num) / num;
					float num4 = ((float)i + 0.5f - num) / num;
					float num5 = num3 * num3 + num4 * num4;
					float num6 = ((num5 < 1f) ? ((Mathf.Exp(-3.2f * num5) - num2) / (1f - num2)) : 0f);
					array[i * 64 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.RoundToInt(Mathf.Clamp01(num6) * 255f));
				}
			}
			val.SetPixels32(array);
			val.Apply(false, true);
			Sprite obj = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 64f, 0u, (SpriteMeshType)0);
			((Object)obj).name = "Gnomes_FairyAuraSprite";
			((Object)obj).hideFlags = (HideFlags)61;
			return obj;
		}
	}
	internal static class FairyConfig
	{
		public static readonly bool LightOn = true;

		public static readonly bool SparklesOn = true;

		public static readonly bool SummonOn = true;

		public static readonly float DetailDistance = 45f;
	}
	internal class FairyEntity : MonoBehaviour, IInteractable, ICrosshairTarget
	{
		private sealed class Sparkle
		{
			public Transform T;

			public MeshRenderer R;

			public Vector3 Offset;

			public Vector3 Velocity;

			public float Age;

			public float Life;

			public float Size;
		}

		public static FairyEntity Current;

		public const float HoverHeight = 1.2f;

		private const float NearDistance = 34f;

		private const int MaxSparkles = 12;

		private const float WingOpenBase = 26f;

		private const float WingOpenSwing = 15f;

		private const float WingOpenCharge = 8f;

		public const float WingOpenMin = 3f;

		public const float WingOpenMax = 41f;

		private const float ScreenRadius = 2.5f;

		private const float DetailReturn = 0.9f;

		private const float MotionEaseIn = 0.6f;

		private const float MotionEaseOut = 0.4f;

		private const float LookDistance = 9f;

		private const float LookRelease = 11f;

		private const float TurnSmooth = 0.9f;

		private const float TurnMaxSpeed = 75f;

		private const float TwirlMin = 0.7f;

		private const float TwirlMax = 1.6f;

		public const float CastWindup = 0.55f;

		private const float CastSwing = 0.16f;

		private const float CastRecover = 0.6f;

		private const float CastTotal = 1.3100001f;

		public const float CastRelease = 0.646f;

		private const float CastReleaseAt = 0.6f;

		private const float CastLeanBack = 17f;

		private const float CastLeanThrough = -26f;

		private const float CastRollUp = -22f;

		private const float CastRollThrough = 10f;

		private const float CastStepBack = -0.1f;

		private const float CastStepThrough = 0.17f;

		private const float CastRise = 0.14f;

		private const float CastTurnSmooth = 0.16f;

		private const float CastTurnMaxSpeed = 540f;

		private static readonly Vector3 StaffTipLocal = new Vector3(-12.5f, 79.5f, -3f) * 0.0175f;

		public const float SummonRaise = 0.65f;

		private const float SummonHold = 0.4f;

		private const float SummonPoint = 0.22f;

		private const float SummonRecover = 0.6f;

		private const float SummonTotalSeconds = 1.87f;

		public const float SummonLight = 1.171f;

		private const float SummonRise = 0.55f;

		private const float SummonLeanUp = -9f;

		private const float SummonRollUp = -34f;

		private const float SummonLeanPoint = 9f;

		private const float SummonRollPoint = -5f;

		private const float SummonStepPoint = 0.1f;

		private float _summonStart = -100f;

		private Vector3 _summonTarget;

		private float _castStart = -100f;

		private Vector3 _castTarget;

		private Transform _hover;

		private Transform _wingL;

		private Transform _wingR;

		private Transform _core;

		private MeshRenderer _body;

		private MeshRenderer _wingLR;

		private MeshRenderer _wingRR;

		private MeshRenderer _coreR;

		private Light _light;

		private MeshFilter _bodyF;

		private MeshFilter _wingLF;

		private MeshFilter _wingRF;

		private MeshFilter _coreF;

		private Mesh _bodyFull;

		private Mesh _wingFull;

		private Mesh _coreFull;

		private Mesh _bodyLod;

		private Mesh _wingLod;

		private Mesh _coreLod;

		private bool _detail = true;

		private float _phase;

		private float _yaw;

		private float _yawSpeed;

		private bool _watching;

		private float _twirlStart;

		private float _twirlEnd = -1f;

		private float _flap;

		private float _motion;

		private float _seed;

		private bool _highlighted;

		private bool _tintAtRest = true;

		private float _charge;

		private float _chargeUntil = -1f;

		private float _burst;

		private readonly List<Sparkle> _sparkles = new List<Sparkle>(12);

		private Transform _sparkleRoot;

		private float _nextSparkle;

		private int _live;

		private static readonly int BaseColorId = Shader.PropertyToID("_BaseColor");

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

		private static readonly int EmissionId = Shader.PropertyToID("_EmissionColor");

		private MaterialPropertyBlock _mpb;

		private FairyAura _aura;

		private bool _auraTried;

		private static readonly Color GlowColor = new Color(1f, 0.93f, 0.64f);

		private static readonly Color WingColor = new Color(0.72f, 0.95f, 1f);

		private const float AimSlack = 0.12f;

		private const float AimRadius = 0.42f;

		private static Vector3 _wingCenter;

		private static Vector3 _wingHalf;

		private static bool _aimShapesReady;

		public Vector3 BodyWorld
		{
			get
			{
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: 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_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_hover != (Object)null))
				{
					return ((Component)this).transform.position + Vector3.up * 1.2f;
				}
				return _hover.position + Vector3.up * 0.7525f;
			}
		}

		public Vector3 CoreWorld
		{
			get
			{
				//IL_001b: 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)
				if (!((Object)(object)_core != (Object)null))
				{
					return BodyWorld;
				}
				return _core.position;
			}
		}

		public Vector3 StaffTipWorld
		{
			get
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_hover != (Object)null))
				{
					return ((Component)this).transform.position + Vector3.up * (1.2f + StaffTipLocal.y);
				}
				return _hover.TransformPoint(StaffTipLocal);
			}
		}

		public Vector3 FacingWorld => ((Component)this).transform.rotation * (Quaternion.Euler(0f, _yaw, 0f) * Vector3.back);

		public bool Casting => Time.unscaledTime - _castStart < 1.3100001f;

		public bool Summoning => Time.unscaledTime - _summonStart < 1.87f;

		public float SummonCharge { get; private set; }

		public bool Twirling
		{
			get
			{
				if (_twirlEnd > 0f)
				{
					return Time.unscaledTime < _twirlEnd;
				}
				return false;
			}
		}

		public float CastCharge { get; private set; }

		public float Excitement => Mathf.Clamp01(_charge + _burst);

		public void Init(Transform hover, MeshRenderer body, Transform wingL, Transform wingR, MeshRenderer wingLR, MeshRenderer wingRR, Transform core, MeshRenderer coreRenderer, Light light)
		{
			_hover = hover;
			_body = body;
			_wingL = wingL;
			_wingR = wingR;
			_wingLR = wingLR;
			_wingRR = wingRR;
			_core = core;
			_coreR = coreRenderer;
			_light = light;
			_phase = Random.value * 10f;
			_seed = _phase;
			_flap = Random.value * MathF.PI * 2f;
			_bodyF = FilterOf(body);
			_wingLF = FilterOf(wingLR);
			_wingRF = FilterOf(wingRR);
			_coreF = FilterOf(coreRenderer);
			_bodyFull = (((Object)(object)_bodyF != (Object)null) ? _bodyF.sharedMesh : null);
			_wingFull = (((Object)(object)_wingLF != (Object)null) ? _wingLF.sharedMesh : null);
			_coreFull = (((Object)(object)_coreF != (Object)null) ? _coreF.sharedMesh : null);
			VoxelLibrary.GetFairyLod(out _bodyLod, out _wingLod, out _coreLod);
			ApplyPose(0f);
		}

		private static MeshFilter FilterOf(MeshRenderer renderer)
		{
			if (!((Object)(object)renderer != (Object)null))
			{
				return null;
			}
			return ((Component)renderer).GetComponent<MeshFilter>();
		}

		private void OnEnable()
		{
			Current = this;
		}

		private void OnDisable()
		{
			if ((Object)(object)Current == (Object)(object)this)
			{
				Current = null;
			}
			_aura?.Hide();
		}

		private void OnDestroy()
		{
			if ((Object)(object)_sparkleRoot != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_sparkleRoot).gameObject);
			}
			_aura?.Destroy();
			_aura = null;
		}

		public void BeginCharge(float seconds)
		{
			float unscaledTime = Time.unscaledTime;
			_chargeUntil = unscaledTime + Mathf.Clamp(seconds, 0.1f, 3f);
			if (!(unscaledTime < _twirlEnd) && !Casting && !Summoning)
			{
				float num = Mathf.Clamp(_chargeUntil - unscaledTime, 0.7f, 1.6f);
				_twirlEnd = Mathf.Max(_chargeUntil, unscaledTime + num);
				_twirlStart = _twirlEnd - num;
			}
		}

		public void Flash()
		{
			_burst = 1f;
		}

		public void BeginCast(Vector3 target)
		{
			//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)
			_castTarget = target;
			_castStart = Time.unscaledTime;
		}

		public void BeginSummon(Vector3 target)
		{
			//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)
			_summonTarget = target;
			_summonStart = Time.unscaledTime;
		}

		private void SummonPose(float now, ref float lean, ref float roll, ref float step, ref float rise)
		{
			float num = now - _summonStart;
			if (num < 0f || num >= 1.87f)
			{
				SummonCharge = 0f;
			}
			else if (num < 0.65f)
			{
				float num2 = Ease(num / 0.65f);
				lean += -9f * num2;
				roll += -34f * num2;
				rise += 0.55f * num2;
				SummonCharge = num2 * 0.8f;
			}
			else if (num < 1.05f)
			{
				lean += -9f;
				roll += -34f;
				rise += 0.55f;
				SummonCharge = 0.8f + 0.2f * Ease((num - 0.65f) / 0.4f);
			}
			else if (num < 1.27f)
			{
				float num3 = (num - 0.65f - 0.4f) / 0.22f;
				float num4 = Ease(num3);
				lean += Mathf.Lerp(-9f, 9f, num4);
				roll += Mathf.Lerp(-34f, -5f, num4);
				step += 0.1f * num4;
				rise += 0.55f * (1f - num4 * 0.6f);
				SummonCharge = ((num3 < 0.55f) ? 1f : (1f - Mathf.Clamp01((num3 - 0.55f) / 0.45f)));
			}
			else
			{
				float num5 = Ease((num - 0.65f - 0.4f - 0.22f) / 0.6f);
				lean += 9f * (1f - num5);
				roll += -5f * (1f - num5);
				step += 0.1f * (1f - num5);
				rise += 0.22000001f * (1f - num5);
				SummonCharge = 0f;
			}
		}

		private float SummonYaw()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return YawTo(_summonTarget);
		}

		private void CastPose(float now, out float lean, out float roll, out float step, out float rise)
		{
			float num = now - _castStart;
			if (num < 0f || num >= 1.3100001f)
			{
				lean = (roll = (step = (rise = 0f)));
				CastCharge = 0f;
			}
			else if (num < 0.55f)
			{
				float num2 = Ease(num / 0.55f);
				lean = 17f * num2;
				roll = -22f * num2;
				step = -0.1f * num2;
				rise = 0.14f * num2;
				CastCharge = num2;
			}
			else if (num < 0.71000004f)
			{
				float num3 = (num - 0.55f) / 0.16f;
				float num4 = Ease(num3);
				lean = Mathf.Lerp(17f, -26f, num4);
				roll = Mathf.Lerp(-22f, 10f, num4);
				step = Mathf.Lerp(-0.1f, 0.17f, num4);
				rise = 0.14f * (1f - num4);
				CastCharge = ((num3 < 0.6f) ? 1f : (1f - Mathf.Clamp01((num3 - 0.6f) / 0.39999998f)));
			}
			else
			{
				float num5 = Ease((num - 0.55f - 0.16f) / 0.6f);
				lean = -26f * (1f - num5);
				roll = 10f * (1f - num5);
				step = 0.17f * (1f - num5);
				rise = 0f;
				CastCharge = 0f;
			}
		}

		private float CastYaw()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return YawTo(_castTarget);
		}

		private float YawTo(Vector3 target)
		{
			//IL_0000: 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_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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = target - ((Component)this).transform.position;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.04f)
			{
				return _yaw;
			}
			Vector3 val2 = ((Component)this).transform.InverseTransformDirection(val);
			return Mathf.Atan2(0f - val2.x, 0f - val2.z) * 57.29578f;
		}

		private static float Ease(float t)
		{
			t = Mathf.Clamp01(t);
			return t * t * (3f - 2f * t);
		}

		private void LateUpdate()
		{
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_hover == (Object)null)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			float num = Mathf.Min(Time.unscaledDeltaTime, 0.1f);
			float num2 = ((_chargeUntil > 0f && unscaledTime < _chargeUntil) ? 1f : 0f);
			if (num2 <= 0f && _chargeUntil > 0f && unscaledTime >= _chargeUntil)
			{
				_chargeUntil = -1f;
			}
			_charge = Mathf.MoveTowards(_charge, num2, num * ((num2 > _charge) ? 1.6f : 2.5f));
			_burst = Mathf.MoveTowards(_burst, 0f, num * 1.6f);
			bool flag = _chargeUntil > 0f || _charge > 0.01f || _burst > 0.01f;
			Camera val = GnomeCamera.Get();
			UpdateDetail(val);
			bool flag2 = (Object)(object)val != (Object)null && FairyFireflies.OnScreen(BodyWorld, 2.5f);
			bool flag3 = Casting || Summoning;
			bool flag4 = _detail || flag || flag3;
			if ((flag2 || flag3) && (flag4 || _motion > 0f))
			{
				Animate(num, flag4);
			}
			UpdateAura(val, flag2 && flag4, unscaledTime);
			bool flag5 = PlayerNear(34f);
			if (flag5 || flag)
			{
				if ((Object)(object)_light != (Object)null)
				{
					_light.intensity = 2.2f + Mathf.Sin((unscaledTime + _seed) * 2.6f) * 0.35f + _charge * 5f + _burst * 12f;
					_light.range = 9f + _charge * 5f + _burst * 10f;
				}
				if (flag2)
				{
					ApplyTint();
				}
			}
			else if (flag2 && !_tintAtRest)
			{
				ApplyTint();
			}
			Show((Renderer)(object)_body);
			Show((Renderer)(object)_coreR);
			Show((Renderer)(object)_wingLR);
			Show((Renderer)(object)_wingRR);
			if ((Object)(object)_light != (Object)null)
			{
				bool lightOn = FairyConfig.LightOn;
				if (((Behaviour)_light).enabled != lightOn)
				{
					((Behaviour)_light).enabled = lightOn;
				}
			}
			TickSparkles(num, flag5 && flag2);
		}

		private static void Show(Renderer renderer)
		{
			if ((Object)(object)renderer != (Object)null && !renderer.enabled)
			{
				renderer.enabled = true;
			}
		}

		private void UpdateDetail(Camera cam)
		{
			//IL_0022: 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_0058: 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_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_0092: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			float detailDistance = FairyConfig.DetailDistance;
			bool flag = true;
			if (detailDistance > 0f)
			{
				Vector3 position;
				if ((Object)(object)cam != (Object)null)
				{
					position = ((Component)cam).transform.position;
				}
				else
				{
					FirstPersonController val = (((Object)(object)GameManager.Instance != (Object)null) ? GameManager.Instance.LocalPlayer : null);
					if ((Object)(object)val == (Object)null)
					{
						return;
					}
					position = ((Component)val).transform.position;
				}
				float num = (_detail ? detailDistance : (detailDistance * 0.9f));
				Vector3 val2 = ((Component)this).transform.position + Vector3.up * 1.2f;
				Vector3 val3 = position - val2;
				flag = ((Vector3)(ref val3)).sqrMagnitude < num * num;
			}
			if (flag != _detail)
			{
				_detail = flag;
				SetMesh(_bodyF, flag ? _bodyFull : _bodyLod);
				SetMesh(_wingLF, flag ? _wingFull : _wingLod);
				SetMesh(_wingRF, flag ? _wingFull : _wingLod);
				SetMesh(_coreF, flag ? _coreFull : _coreLod);
			}
		}

		private static void SetMesh(MeshFilter filter, Mesh mesh)
		{
			if ((Object)(object)filter != (Object)null && (Object)(object)mesh != (Object)null && (Object)(object)filter.sharedMesh != (Object)(object)mesh)
			{
				filter.sharedMesh = mesh;
			}
		}

		private void UpdateAura(Camera cam, bool visible, float now)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (_aura != null && !_aura.Alive)
			{
				_aura = null;
				_auraTried = false;
			}
			if (!visible || (Object)(object)cam == (Object)null)
			{
				_aura?.Hide();
				return;
			}
			if (_aura == null)
			{
				if (_auraTried)
				{
					return;
				}
				_auraTried = true;
				_aura = FairyAura.Create();
				if (_aura == null)
				{
					return;
				}
			}
			_aura.Tick(cam, BodyWorld, _charge, _burst, _highlighted, now);
		}

		private void Animate(float dt, bool wantMotion)
		{
			_motion = Mathf.MoveTowards(_motion, wantMotion ? 1f : 0f, dt / (wantMotion ? 0.6f : 0.4f));
			float m = _motion * _motion * (3f - 2f * _motion);
			_phase += dt;
			_flap = Mathf.Repeat(_flap + dt * (9f + _charge * 12f + CastCharge * 10f + SummonCharge * 10f), MathF.PI * 2f);
			if (wantMotion && dt > 0f)
			{
				float num;
				float num2;
				float num3;
				if (Casting)
				{
					num = CastYaw();
					num2 = 0.16f;
					num3 = 540f;
				}
				else if (Summoning)
				{
					num = SummonYaw();
					num2 = 0.32f;
					num3 = 540f;
				}
				else
				{
					num = LookTarget(out var watching);
					_watching = watching;
					num2 = 0.9f;
					num3 = 75f;
				}
				_yaw = Mathf.Repeat(Mathf.SmoothDampAngle(_yaw, num, ref _yawSpeed, num2, num3, dt), 360f);
			}
			ApplyPose(m);
		}

		private float LookTarget(out bool watching)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			watching = false;
			float num = (_watching ? 11f : 9f);
			float num2 = num * num;
			Vector3 position = ((Component)this).transform.position;
			Vector3 val = default(Vector3);
			List<FirstPersonController> localPlayers = FirstPersonController.LocalPlayers;
			if (localPlayers != null)
			{
				for (int i = 0; i < localPlayers.Count; i++)
				{
					FirstPersonController val2 = localPlayers[i];
					if (!((Object)(object)val2 == (Object)null) && ((Behaviour)val2).isActiveAndEnabled)
					{
						Vector3 val3 = ((Component)val2).transform.position - position;
						val3.y = 0f;
						float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
						if (sqrMagnitude < num2)
						{
							num2 = sqrMagnitude;
							val = val3;
							watching = true;
						}
					}
				}
			}
			if (!watching)
			{
				return 0f;
			}
			if (num2 < 0.04f)
			{
				return _yaw;
			}
			Vector3 val4 = ((Component)this).transform.InverseTransformDirection(val);
			return Mathf.Atan2(0f - val4.x, 0f - val4.z) * 57.29578f;
		}

		private float Twirl(float now)
		{
			if (_twirlEnd <= 0f || now <= _twirlStart)
			{
				return 0f;
			}
			if (now >= _twirlEnd)
			{
				_twirlEnd = -1f;
				return 0f;
			}
			float num = (now - _twirlStart) / (_twirlEnd - _twirlStart);
			return 360f * num * num * num * (num * (6f * num - 15f) + 10f);
		}

		private void ApplyPose(float m)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: 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_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			float unscaledTime = Time.unscaledTime;
			CastPose(unscaledTime, out var lean, out var roll, out var step, out var rise);
			SummonPose(unscaledTime, ref lean, ref roll, ref step, ref rise);
			float num = Mathf.Sin(_phase * 1.75f) * 0.15f + Mathf.Sin(_phase * 4.1f) * 0.03f + _charge * 0.3f;
			Vector3 val = Quaternion.Euler(0f, _yaw, 0f) * Vector3.back * step;
			_hover.localPosition = new Vector3(val.x, 1.2f + num * m + rise, val.z);
			_hover.localRotation = Quaternion.Euler(lean, _yaw + Twirl(unscaledTime), Mathf.Sin(_phase * 0.9f) * 5f * m + roll);
			float num2 = 26f + (Mathf.Sin(_flap) * 15f - _charge * 8f) * m;
			if ((Object)(object)_wingL != (Object)null)
			{
				_wingL.localRotation = Quaternion.Euler(0f, 0f - num2, 12f);
			}
			if ((Object)(object)_wingR != (Object)null)
			{
				_wingR.localRotation = Quaternion.Euler(0f, num2, -12f);
			}
			float num3 = 1f + Mathf.Sin(_phase * 3.4f) * 0.12f;
			float num4 = Mathf.LerpUnclamped(1f, num3 * (1f + _charge * 1.5f + _burst * 2.2f), m);
			if ((Object)(object)_core != (Object)null)
			{
				_core.localScale = Vector3.one * num4;
			}
		}

		private void TickSparkles(float dt, bool near)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: 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_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			bool flag = near && FairyConfig.SparklesOn;
			if (!flag && _live == 0)
			{
				return;
			}
			if (flag && Time.unscaledTime >= _nextSparkle)
			{
				_nextSparkle = Time.unscaledTime + ((_charge > 0.05f) ? 0.03f : 0.12f);
				Spawn();
			}
			Vector3 val = (((Object)(object)_hover != (Object)null) ? _hover.position : (((Component)this).transform.position + Vector3.up * 1.2f));
			float num = ((Component)this).transform.position.y + 0.03f;
			for (int i = 0; i < _sparkles.Count; i++)
			{
				Sparkle sparkle = _sparkles[i];
				if (!((Object)(object)sparkle.T == (Object)null) && !(sparkle.Age >= sparkle.Life))
				{
					sparkle.Age += dt;
					sparkle.Offset += sparkle.Velocity * dt;
					sparkle.Velocity.y -= 0.3f * dt;
					Vector3 val2 = val + sparkle.Offset;
					if (sparkle.Age >= sparkle.Life || val2.y < num)
					{
						sparkle.Age = sparkle.Life;
						_live--;
						((Renderer)sparkle.R).enabled = false;
						((Component)sparkle.T).gameObject.SetActive(false);
					}
					else
					{
						sparkle.T.position = val2;
						sparkle.T.Rotate(0f, 180f * dt, 90f * dt, (Space)1);
						float num2 = sparkle.Age / sparkle.Life;
						sparkle.T.localScale = Vector3.one * Mathf.Max(0.0005f, sparkle.Size * Mathf.Min(1f, num2 * 6f) * (1f - num2 * num2));
						((Renderer)sparkle.R).enabled = true;
					}
				}
			}
		}

		private bool PlayerNear(float distance)
		{
			//IL_002c: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			FirstPersonController val = (((Object)(object)GameManager.Instance != (Object)null) ? GameManager.Instance.LocalPlayer : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Vector3 val2 = ((Component)val).transform.position - ((Component)this).transform.position;
			return ((Vector3)(ref val2)).sqrMagnitude < distance * distance;
		}

		private void Spawn()
		{
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: 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_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: 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_00d3: Expected O, but got Unknown
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			Sparkle sparkle = null;
			for (int i = 0; i < _sparkles.Count; i++)
			{
				if ((Object)(object)_sparkles[i].T != (Object)null && _sparkles[i].Age >= _sparkles[i].Life)
				{
					sparkle = _sparkles[i];
					break;
				}
			}
			if (sparkle == null)
			{
				if (_sparkles.Count >= 12)
				{
					return;
				}
				VoxelLibrary.GetFairySparkle(out var mesh, out var material);
				if ((Object)(object)mesh == (Object)null || (Object)(object)material == (Object)null)
				{
					return;
				}
				if ((Object)(object)_sparkleRoot == (Object)null)
				{
					GameObject val = new GameObject("Gnomes_FairySparkles");
					_sparkleRoot = val.transform;
				}
				GameObject val2 = new GameObject("Sparkle");
				val2.transform.SetParent(_sparkleRoot, false);
				val2.AddComponent<MeshFilter>().sharedMesh = mesh;
				MeshRenderer val3 = val2.AddComponent<MeshRenderer>();
				((Renderer)val3).sharedMaterial = material;
				((Renderer)val3).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)val3).receiveShadows = false;
				sparkle = new Sparkle
				{
					T = val2.transform,
					R = val3
				};
				_sparkles.Add(sparkle);
			}
			float num = 1.505f;
			float num2 = Random.value * MathF.PI * 2f;
			float num3 = Random.Range(0.14f, 0.55f) * num;
			sparkle.Offset = new Vector3(Mathf.Cos(num2) * num3, Random.Range(-0.1f, 0.55f) * num, Mathf.Sin(num2) * num3);
			sparkle.Velocity = new Vector3(Mathf.Cos(num2) * 0.15f, Random.Range(-0.28f, -0.08f), Mathf.Sin(num2) * 0.15f);
			sparkle.Age = 0f;
			sparkle.Life = Random.Range(0.9f, 1.7f);
			sparkle.Size = Random.Range(0.45f, 0.95f);
			((Component)sparkle.T).gameObject.SetActive(true);
			sparkle.T.rotation = Random.rotation;
			Tint((Renderer)(object)sparkle.R, Color.Lerp(GlowColor, WingColor, Random.value * 0.6f), 2.6f);
			_live++;
		}

		private void ApplyTint()
		{
			//IL_0054: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f + _charge * 2.2f + _burst * 4f + Mathf.Sin(_phase * 3.4f) * 0.15f;
			float num2 = (_highlighted ? 1.4f : 1f);
			Tint((Renderer)(object)_coreR, GlowColor, 2.4f * num * num2);
			Tint((Renderer)(object)_wingLR, WingColor, (1.1f + _charge) * num2);
			Tint((Renderer)(object)_wingRR, WingColor, (1.1f + _charge) * num2);
			_tintAtRest = _charge <= 0.01f && _burst <= 0.01f;
		}

		private void Tint(Renderer renderer, Color color, float emission)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			if (!((Object)(object)renderer == (Object)null))
			{
				if (_mpb == null)
				{
					_mpb = new MaterialPropertyBlock();
				}
				_mpb.Clear();
				_mpb.SetColor(BaseColorId, color);
				_mpb.SetColor(ColorId, color);
				_mpb.SetColor(EmissionId, color * emission);
				renderer.SetPropertyBlock(_mpb);
			}
		}

		public void Interact(FirstPersonController owner)
		{
			ShopWindow.Instance?.Open(this);
		}

		public void OnCrosshairEnter()
		{
			_highlighted = true;
			Highlight.Set((Renderer)(object)_body, on: true);
		}

		public void OnCrosshairExit()
		{
			_highlighted = false;
			Highlight.Set((Renderer)(object)_body, on: false);
		}

		public string GetInteractionText()
		{
			return Lang.T("Falar com Fada dos Gnomos", "Talk to the Gnome Fairy");
		}

		public string GetInteractionInput()
		{
			return "<style=Player/Interact> ";
		}

		public string GetInteractionStatInfo()
		{
			return string.Empty;
		}

		public float GetInteractionDistance()
		{
			return 7f;
		}

		public bool AimHit(Ray ray, float reach, out float distance)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//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_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_005f: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			distance = 0f;
			if ((Object)(object)_hover == (Object)null)
			{
				return false;
			}
			float num = 1.505f;
			float num2 = reach + num;
			Vector3 val = BodyWorld - ((Ray)(ref ray)).origin;
			if (((Vector3)(ref val)).sqrMagnitude > num2 * num2)
			{
				return false;
			}
			if (!_aimShapesReady)
			{
				VoxelLibrary.FairyWingBounds(3f, 41f, out var center, out var size);
				_wingCenter = center;
				_wingHalf = (size + Vector3.one * 0.12f) * 0.5f;
				_aimShapesReady = true;
			}
			Vector3 o = _hover.InverseTransformPoint(((Ray)(ref ray)).origin);
			Vector3 d = _hover.InverseTransformDirection(((Ray)(ref ray)).direction);
			float num3 = float.MaxValue;
			float num4 = (num + 0.24f) * 0.5f - 0.42f;
			float num5 = num * 0.5f;
			if (RayCapsuleY(o, d, num5 - num4, num5 + num4, 0.42f, out var t))
			{
				num3 = t;
			}
			if (RayBox(o, d, _wingCenter, _wingHalf, out t) && t < num3)
			{
				num3 = t;
			}
			if (num3 > reach)
			{
				return false;
			}
			distance = num3;
			return true;
		}

		private static bool RayCapsuleY(Vector3 o, Vector3 d, float y0, float y1, float r, out float t)
		{
			//IL_0008: 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_001c: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			t = float.MaxValue;
			float num = Mathf.Clamp(o.y, y0, y1);
			if (o.x * o.x + (o.y - num) * (o.y - num) + o.z * o.z <= r * r)
			{
				return false;
			}
			float num2 = d.x * d.x + d.z * d.z;
			if (num2 > 1E-08f)
			{
				float num3 = o.x * d.x + o.z * d.z;
				float num4 = o.x * o.x + o.z * o.z - r * r;
				float num5 = num3 * num3 - num2 * num4;
				if (num5 >= 0f)
				{
					float num6 = (0f - num3 - Mathf.Sqrt(num5)) / num2;
					float num7 = o.y + d.y * num6;
					if (num6 >= 0f && num7 >= y0 && num7 <= y1)
					{
						t = num6;
					}
				}
			}
			RaySphere(o, d, y0, r, ref t);
			RaySphere(o, d, y1, r, ref t);
			return t < float.MaxValue;
		}

		private static void RaySphere(Vector3 o, Vector3 d, float cy, float r, ref float t)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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)
			float x = o.x;
			float num = o.y - cy;
			float z = o.z;
			float num2 = x * d.x + num * d.y + z * d.z;
			float num3 = x * x + num * num + z * z - r * r;
			float num4 = num2 * num2 - num3;
			if (!(num4 < 0f))
			{
				float num5 = 0f - num2 - Mathf.Sqrt(num4);
				if (num5 >= 0f && num5 < t)
				{
					t = num5;
				}
			}
		}

		private static bool RayBox(Vector3 o, Vector3 d, Vector3 center, Vector3 half, out float t)
		{
			t = 0f;
			float num = float.MinValue;
			float num2 = float.MaxValue;
			for (int i = 0; i < 3; i++)
			{
				float num3 = ((Vector3)(ref center))[i] - ((Vector3)(ref half))[i];
				float num4 = ((Vector3)(ref center))[i] + ((Vector3)(ref half))[i];
				float num5 = ((Vector3)(ref o))[i];
				float num6 = ((Vector3)(ref d))[i];
				if (Mathf.Abs(num6) < 1E-08f)
				{
					if (num5 < num3 || num5 > num4)
					{
						return false;
					}
					continue;
				}
				float num7 = (num3 - num5) / num6;
				float num8 = (num4 - num5) / num6;
				if (num7 > num8)
				{
					float num9 = num8;
					num8 = num7;
					num7 = num9;
				}
				if (num7 > num)
				{
					num = num7;
				}
				if (num8 < num2)
				{
					num2 = num8;
				}
				if (num > num2)
				{
					return false;
				}
			}
			if (num < 0f)
			{
				return false;
			}
			t = num;
			return true;
		}
	}
	[DefaultExecutionOrder(670)]
	internal class FairyFireflies : MonoBehaviour
	{
		private sealed class Firefly
		{
			public float Radius;

			public float Height;

			public float Speed;

			public float Tight;

			public float Size;

			public float Angle;

			public float DriftR;

			public float DriftRPhase;

			public float DriftY;

			public float DriftYPhase;

			public float DriftA;

			public float DriftAPhase;

			public float BlinkPeriod;

			public float BlinkPhase;

			public float BlinkT;

			public float OnFraction;

			public int Hue;
		}

		public const int MaxCount = 16;

		private const int TrailNodes = 3;

		private const int Copies = 4;

		private const float TrailLag = 0.055f;

		private const float NearDistance = 34f;

		private const float EffectRadius = 3.2f;

		private static readonly Bounds SwarmBounds = new Bounds(Vector3.zero, Vector3.one * 8f);

		private readonly Firefly[] _flies = new Firefly[16];

		private Transform _root;

		private Mesh _mesh;

		private MeshRenderer _renderer;

		private Vector3[] _baseVertices;

		private Vector3[] _baseNormals;

		private int[] _baseTriangles;

		private Vector3[] _vertices;

		private Vector2[] _uvs;

		private int[] _copyLevel;

		private int[] _copyHue;

		private bool[] _copyHidden;

		private bool _uvDirty;

		private int _builtFor = -1;

		private bool _hidden;

		private float _nextErrorLog;

		private static readonly int[] TrailLevel = BuildTrailLevels();

		private static readonly Plane[] Frustum = (Plane[])(object)new Plane[6];

		private static int _frustumFrame = -1;

		private static Camera _frustumCamera;

		private static bool On => Plugin.FairyFireflies;

		private static int Wanted => Mathf.Clamp(Plugin.FairyFireflyCount, 0, 16);

		private void OnDestroy()
		{
			if ((Object)(object)_mesh != (Object)null)
			{
				Object.Destroy((Object)(object)_mesh);
			}
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_root).gameObject);
			}
		}

		private void LateUpdate()
		{
			//IL_0026: 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_0048: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				FairyEntity current = FairyEntity.Current;
				int wanted = Wanted;
				if ((Object)(object)current == (Object)null || !On || wanted <= 0 || !PlayerNear(((Component)current).transform.position))
				{
					Hide();
					return;
				}
				Vector3 bodyWorld = current.BodyWorld;
				if (!OnScreen(bodyWorld, 3.2f) || !Build(wanted))
				{
					return;
				}
				_hidden = false;
				_root.position = bodyWorld;
				float num = Mathf.Min(Time.unscaledDeltaTime, 0.1f);
				float unscaledTime = Time.unscaledTime;
				float excitement = current.Excitement;
				for (int i = 0; i < wanted; i++)
				{
					ref Firefly reference = ref _flies[i];
					Firefly firefly = reference ?? (reference = Create(i));
					firefly.Angle = Mathf.Repeat(firefly.Angle + firefly.Speed * Speedup(excitement) * num, MathF.PI * 2f);
					firefly.BlinkT += num * (1f + excitement * 1.8f);
					int num2 = i * 4;
					float num3 = Blink(firefly, excitement);
					if (num3 <= 0.03f)
					{
						for (int j = 0; j < 4; j++)
						{
							Collapse(num2 + j);
						}
						continue;
					}
					float num4 = firefly.Size * (0.45f + 0.55f * num3) * (1f + excitement * 0.35f);
					Draw(num2, Sample(firefly, unscaledTime, 0f, excitement), num4, firefly.Hue, LevelFor(1.1f + 2.7f * num3));
					bool flag = num3 > 0.16f;
					for (int k = 0; k < 3; k++)
					{
						if (flag)
						{
							Draw(num2 + 1 + k, Sample(firefly, unscaledTime, 0.055f * (float)(k + 1), excitement), num4 * TrailScale(k), firefly.Hue, TrailLevel[k]);
						}
						else
						{
							Collapse(num2 + 1 + k);
						}
					}
				}
				_mesh.SetVertices(_vertices);
				if (_uvDirty)
				{
					_uvDirty = false;
					_mesh.SetUVs(0, _uvs);
				}
				_mesh.bounds = SwarmBounds;
				((Renderer)_renderer).enabled = true;
			}
			catch (Exception ex)
			{
				LogError("vaga-lumes da fada", ex);
			}
		}

		private static float Speedup(float excited)
		{
			return 1f + excited * 2.4f;
		}

		private static float TrailScale(int node)
		{
			return node switch
			{
				1 => 0.4f, 
				0 => 0.62f, 
				_ => 0.26f, 
			};
		}

		private static Vector3 Sample(Firefly f, float now, float lag, float excited)
		{
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			float num = now - lag;
			float num2 = f.Angle - f.Speed * Speedup(excited) * lag + Mathf.Sin(num * f.DriftA + f.DriftAPhase) * 0.8f;
			float num3 = f.Radius + Mathf.Sin(num * f.DriftR + f.DriftRPhase) * 0.34f + Mathf.Sin(num * f.DriftR * 2.7f) * 0.11f;
			float num4 = f.Height + Mathf.Sin(num * f.DriftY + f.DriftYPhase) * 0.28f;
			if (excited > 0.001f)
			{
				float num5 = excited * 0.85f;
				num3 = Mathf.Lerp(num3, f.Tight, num5);
				num4 = Mathf.Lerp(num4, num4 * 0.3f, num5);
			}
			return new Vector3(Mathf.Cos(num2) * num3, num4, Mathf.Sin(num2) * num3);
		}

		private static float Blink(Firefly f, float excited)
		{
			float num = Mathf.Repeat(f.BlinkT / f.BlinkPeriod + f.BlinkPhase, 1f);
			float num2 = ((num < 0.1f) ? (num / 0.1f) : ((num < f.OnFraction) ? 1f : ((!(num < f.OnFraction + 0.28f)) ? 0f : (1f - (num - f.OnFraction) / 0.28f))));
			num2 *= 0.86f + 0.14f * Mathf.Sin(f.BlinkT * 9f + f.BlinkPhase * 6.3f);
			if (excited > 0.001f)
			{
				num2 = Mathf.Lerp(num2, 0.6f + 0.4f * num2, excited);
			}
			return Mathf.Clamp01(num2);
		}

		private static int LevelFor(float emission)
		{
			return Mathf.Clamp(Mathf.RoundToInt(emission / 3.8f * 16f) - 1, 0, 15);
		}

		private static int[] BuildTrailLevels()
		{
			int[] array = new int[3];
			for (int i = 0; i < 3; i++)
			{
				array[i] = LevelFor(0.9f - (float)i * 0.22f);
			}
			return array;
		}

		private void Draw(int copy, Vector3 position, float size, int hue, int level)
		{
			//IL_001a: 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_0028: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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)
			int num = _baseVertices.Length;
			int num2 = copy * num;
			for (int i = 0; i < num; i++)
			{
				_vertices[num2 + i] = position + _baseVertices[i] * size;
			}
			_copyHidden[copy] = false;
			if (_copyLevel[copy] != level || _copyHue[copy] != hue)
			{
				_copyLevel[copy] = level;
				_copyHue[copy] = hue;
				Vector2 val = VoxelLibrary.FairyDotUv(hue, level);
				for (int j = 0; j < num; j++)
				{
					_uvs[num2 + j] = val;
				}
				_uvDirty = true;
			}
		}

		private void Collapse(int copy)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			if (!_copyHidden[copy])
			{
				_copyHidden[copy] = true;
				int num = _baseVertices.Length;
				int num2 = copy * num;
				for (int i = 0; i < num; i++)
				{
					_vertices[num2 + i] = Vector3.zero;
				}
			}
		}

		private bool Build(int want)
		{
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: 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_006a: Expected O, but got Unknown
			//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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Expected O, but got Unknown
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: 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_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			if (_builtFor == want && (Object)(object)_mesh != (Object)null)
			{
				return true;
			}
			VoxelLibrary.GetFairyDot(out var vertices, out var normals, out var triangles, out var material);
			if (vertices == null || vertices.Length == 0 || (Object)(object)material == (Object)null)
			{
				r