Decompiled source of MorphMod v2.0.0

MorphMod.dll

Decompiled 6 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Splatform;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("MorphMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MorphMod")]
[assembly: AssemblyTitle("MorphMod")]
[assembly: AssemblyVersion("1.0.0.0")]
[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 MorphMod
{
	[HarmonyPatch]
	internal static class ArrivalPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch(typeof(Chat), "SendText")]
		private static bool SendTextPrefix(Type type, string text)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			if (!MorphModPlugin.SuppressArrivalMessage.Value || (int)type != 2)
			{
				return true;
			}
			if (Localization.instance == null)
			{
				return true;
			}
			return text != Localization.instance.Localize("$text_player_arrived");
		}
	}
	internal static class BossMechanics
	{
		private static readonly MethodInfo UpdateRegenerationMethod = AccessTools.Method(typeof(BaseAI), "UpdateRegeneration", (Type[])null, (Type[])null);

		private static readonly FieldRef<MonsterAI, Character> TargetCreature = AccessTools.FieldRefAccess<MonsterAI, Character>("m_targetCreature");

		private static int _solidMask;

		private static int _aimMask;

		private static float _takeOffTime = -9999f;

		private static int SolidMask
		{
			get
			{
				if (_solidMask == 0)
				{
					return _solidMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" });
				}
				return _solidMask;
			}
		}

		private static int AimMask
		{
			get
			{
				if (_aimMask == 0)
				{
					return _aimMask = LayerMask.GetMask(new string[12]
					{
						"Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "vehicle", "character", "character_net", "character_ghost",
						"hitbox", "character_noenv"
					});
				}
				return _aimMask;
			}
		}

		internal static void SetTarget(BaseAI ai, Character target)
		{
			MonsterAI val = (MonsterAI)(object)((ai is MonsterAI) ? ai : null);
			if (val != null)
			{
				TargetCreature.Invoke(val) = target;
			}
		}

		internal static void Regenerate(BaseAI ai, float dt)
		{
			if (Object.op_Implicit((Object)(object)ai) && UpdateRegenerationMethod != null)
			{
				UpdateRegenerationMethod.Invoke(ai, new object[1] { dt });
			}
		}

		internal static bool TogglesFlight(ItemData item)
		{
			if (item.m_shared.m_attack != null)
			{
				return item.m_shared.m_attack.m_toggleFlying;
			}
			return false;
		}

		internal static float LandAltitude(BaseAI ai)
		{
			if (!Object.op_Implicit((Object)(object)ai) || !ai.m_randomFly)
			{
				return 3f;
			}
			return Mathf.Max(ai.m_maxLandAltitude, 2f);
		}

		internal static float GetAltitude(Character mob)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(((Component)mob).transform.position + Vector3.up * 0.5f, Vector3.down, ref val, 1000f, SolidMask, (QueryTriggerInteraction)1))
			{
				return ((Component)mob).transform.position.y - ((RaycastHit)(ref val)).point.y;
			}
			return 1000f;
		}

		internal static string BlockReason(Character mob, BaseAI ai, ItemData item)
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			SharedData shared = item.m_shared;
			float healthPercentage = mob.GetHealthPercentage();
			if (MorphModPlugin.RespectAttackConditions.Value)
			{
				if (shared.m_aiInDungeonOnly && !mob.InInterior())
				{
					return "dungeon only";
				}
				if (shared.m_aiMaxHealthPercentage < 1f && healthPercentage > shared.m_aiMaxHealthPercentage)
				{
					return "HP ≤ " + Mathf.RoundToInt(shared.m_aiMaxHealthPercentage * 100f) + "%";
				}
				if (shared.m_aiMinHealthPercentage > 0f && healthPercentage < shared.m_aiMinHealthPercentage)
				{
					return "HP ≥ " + Mathf.RoundToInt(shared.m_aiMinHealthPercentage * 100f) + "%";
				}
				if (shared.m_aiInMistOnly && !ParticleMist.IsInMist(mob.GetCenterPoint()))
				{
					return "in mist only";
				}
				if (Object.op_Implicit((Object)(object)ai) && !ai.CanUseAttack(item))
				{
					bool flag = mob.IsFlying();
					bool flag2 = mob.IsSwimming();
					if (flag && shared.m_aiWhenFlying)
					{
						return "wrong altitude";
					}
					if (flag)
					{
						return "on ground only";
					}
					if (flag2)
					{
						if (!shared.m_aiWhenWalking)
						{
							return "not in water";
						}
						return "on ground only";
					}
					if (shared.m_aiWhenFlying && !shared.m_aiWhenWalking)
					{
						return "in flight only";
					}
					if (shared.m_aiWhenSwiming && !shared.m_aiWhenWalking)
					{
						return "in water only";
					}
					return "unavailable";
				}
			}
			if (IsTakingOff(mob, ai))
			{
				return "taking off";
			}
			return null;
		}

		internal static float CooldownLeft(Humanoid mob, BaseAI ai, ItemData item)
		{
			float num = Mathf.Max(0f, MorphModPlugin.AttackCooldownScale.Value);
			float num2 = item.m_shared.m_aiAttackInterval * num - (Time.time - item.m_lastAttackTime);
			MonsterAI val = (MonsterAI)(object)((ai is MonsterAI) ? ai : null);
			if (val != null)
			{
				num2 = Mathf.Max(num2, val.m_minAttackInterval * num - ((Character)mob).GetTimeSinceLastAttack());
			}
			return Mathf.Max(0f, num2);
		}

		internal static void OnTakeOff()
		{
			_takeOffTime = Time.time;
		}

		private static bool IsTakingOff(Character mob, BaseAI ai)
		{
			if (Object.op_Implicit((Object)(object)ai) && ai.m_randomFly && mob.IsFlying())
			{
				return Time.time - _takeOffTime < ai.m_takeoffTime;
			}
			return false;
		}

		internal static Vector3 GetAimPoint(Character self, out Character aimed)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			aimed = null;
			Transform transform = ((Component)GameCamera.instance).transform;
			Player localPlayer = Player.m_localPlayer;
			float num = (Object.op_Implicit((Object)(object)self) ? (Vector3.Dot(((Component)self).transform.position - transform.position, transform.forward) - self.GetRadius()) : 0f);
			RaycastHit[] array = Physics.RaycastAll(transform.position, transform.forward, 300f, AimMask, (QueryTriggerInteraction)1);
			Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
			RaycastHit[] array2 = array;
			for (int num2 = 0; num2 < array2.Length; num2++)
			{
				RaycastHit val = array2[num2];
				Character componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Character>();
				if ((!Object.op_Implicit((Object)(object)componentInParent) || (!((Object)(object)componentInParent == (Object)(object)self) && !((Object)(object)componentInParent == (Object)(object)localPlayer))) && (Object.op_Implicit((Object)(object)componentInParent) || !(((RaycastHit)(ref val)).distance < num)))
				{
					if (Object.op_Implicit((Object)(object)componentInParent) && !componentInParent.IsDead() && BaseAI.IsEnemy(self, componentInParent))
					{
						aimed = componentInParent;
					}
					return ((RaycastHit)(ref val)).point;
				}
			}
			return transform.position + transform.forward * 300f;
		}

		internal static Character FindAimAssistTarget(Character self, float maxAngle, float range)
		{
			//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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if (maxAngle <= 0f)
			{
				return null;
			}
			Transform transform = ((Component)GameCamera.instance).transform;
			Character result = null;
			float num = maxAngle;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!Object.op_Implicit((Object)(object)allCharacter) || (Object)(object)allCharacter == (Object)(object)self || allCharacter.IsDead() || !BaseAI.IsEnemy(self, allCharacter))
				{
					continue;
				}
				Vector3 centerPoint = allCharacter.GetCenterPoint();
				if (!(Vector3.Distance(((Component)self).transform.position, centerPoint) > range))
				{
					float num2 = Vector3.Angle(transform.forward, centerPoint - transform.position);
					if (num2 < num)
					{
						num = num2;
						result = allCharacter;
					}
				}
			}
			return result;
		}
	}
	[HarmonyPatch]
	internal static class CritterControl
	{
		private static readonly FieldRef<Fish, float> FishInWater = AccessTools.FieldRefAccess<Fish, float>("m_inWater");

		private static readonly int FlappingHash = ZSyncAnimation.GetHash("flapping");

		private static readonly int FlyingHash = ZSyncAnimation.GetHash("flying");

		private static Vector3 _move;

		private static bool _fast;

		private static bool _down;

		private static Vector3 _birdVelocity;

		internal static void SetInput(Vector3 move, bool fast, bool down)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			_move = move;
			_fast = fast;
			_down = down;
		}

		internal static void Reset()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			_move = Vector3.zero;
			_fast = false;
			_down = false;
			_birdVelocity = Vector3.zero;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Fish), "CustomFixedUpdate")]
		private static bool FishPrefix(Fish __instance, float fixedDeltaTime)
		{
			if (!Possession.IsPossessed((Component)(object)__instance))
			{
				return true;
			}
			DriveFish(__instance, fixedDeltaTime);
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(RandomFlyingBird), "CustomFixedUpdate")]
		private static bool BirdPrefix(RandomFlyingBird __instance, float dt)
		{
			if (!Possession.IsPossessed((Component)(object)__instance))
			{
				return true;
			}
			DriveBird(__instance, dt);
			return false;
		}

		private static void DriveFish(Fish fish, float dt)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: 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_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody component = ((Component)fish).GetComponent<Rigidbody>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			Vector3 position = ((Component)fish).transform.position;
			float num = FishInWater.Invoke(fish);
			bool num2 = num < position.y - fish.m_height;
			bool flag = num <= -10000f || num < position.y + fish.m_height;
			if (num2)
			{
				component.useGravity = true;
				return;
			}
			component.useGravity = false;
			float num3 = fish.m_speed * (_fast ? fish.m_avoidSpeedScale : 1f);
			Vector3 val = _move * num3;
			if (flag && val.y > 0f)
			{
				val.y = 0f;
			}
			float num4 = Mathf.Clamp01(fish.m_acceleration * dt * 2f);
			component.AddForce((val - component.linearVelocity) * num4, (ForceMode)2);
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(_move.x, 0f, _move.z);
			if (((Vector3)(ref val2)).sqrMagnitude > 0.01f)
			{
				float num5 = Mathf.Max(fish.m_turnRate * 4f, 180f) * dt;
				component.rotation = Quaternion.RotateTowards(component.rotation, Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up), num5);
			}
			component.angularVelocity = Vector3.zero;
		}

		private static void DriveBird(RandomFlyingBird bird, float dt)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: 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_019a: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: 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_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			ZNetView component = ((Component)bird).GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid())
			{
				return;
			}
			ZDO zDO = component.GetZDO();
			ZSyncAnimation componentInChildren = ((Component)bird).GetComponentInChildren<ZSyncAnimation>();
			Transform transform = ((Component)bird).transform;
			bool flag = ((Vector3)(ref _move)).sqrMagnitude > 0.01f;
			bool flag2 = zDO.GetBool(ZDOVars.s_landed, false);
			if (flag2 && flag && !_down)
			{
				flag2 = false;
				zDO.Set(ZDOVars.s_landed, false);
			}
			if (flag2)
			{
				_birdVelocity = Vector3.zero;
				Vector3 forward = transform.forward;
				forward.y = 0f;
				if (((Vector3)(ref forward)).sqrMagnitude > 0.0001f)
				{
					transform.rotation = Quaternion.LookRotation(((Vector3)(ref forward)).normalized, Vector3.up);
				}
			}
			else
			{
				float num = bird.m_speed * (_fast ? 2f : 1f);
				_birdVelocity = Vector3.Lerp(_birdVelocity, _move * num, Mathf.Clamp01(dt * 4f));
				Vector3 val = transform.position + _birdVelocity * dt;
				float num2 = float.MinValue;
				float num3 = default(float);
				if (Object.op_Implicit((Object)(object)ZoneSystem.instance) && ZoneSystem.instance.GetSolidHeight(val, ref num3, 1000))
				{
					num2 = Mathf.Max(num3, ZoneSystem.instance.m_waterLevel) + 0.2f;
				}
				if (val.y < num2)
				{
					val.y = num2;
				}
				transform.position = val;
				if (((Vector3)(ref _birdVelocity)).sqrMagnitude > 0.25f)
				{
					Vector3 normalized = ((Vector3)(ref _birdVelocity)).normalized;
					float num4 = Vector3.SignedAngle(transform.forward, normalized, Vector3.up);
					Vector3 val2 = Vector3.Cross(normalized, Vector3.up);
					Vector3 val3 = Vector3.up - val2 * Mathf.Clamp(num4 / 45f, -1f, 1f) * 0.8f;
					transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(normalized, ((Vector3)(ref val3)).normalized), 360f * dt);
				}
				if (_down && !flag && num2 > float.MinValue && val.y - num2 < 0.6f)
				{
					flag2 = true;
					zDO.Set(ZDOVars.s_landed, true);
					_birdVelocity = Vector3.zero;
				}
			}
			if (bird.m_singleModel)
			{
				if (Object.op_Implicit((Object)(object)componentInChildren))
				{
					componentInChildren.SetBool(FlyingHash, !flag2);
				}
			}
			else
			{
				if (Object.op_Implicit((Object)(object)bird.m_landedModel))
				{
					bird.m_landedModel.SetActive(flag2);
				}
				if (Object.op_Implicit((Object)(object)bird.m_flyingModel))
				{
					bird.m_flyingModel.SetActive(!flag2);
				}
			}
			if (Object.op_Implicit((Object)(object)componentInChildren) && !flag2)
			{
				componentInChildren.SetBool(FlappingHash, _fast || _move.y > 0.1f || ((Vector3)(ref _birdVelocity)).magnitude < bird.m_speed * 0.5f);
			}
		}
	}
	[HarmonyPatch]
	internal static class InputPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "TakeInput")]
		private static void PlayerTakeInputPostfix(ref bool __result)
		{
			if (Possession.IsActive || MobMenu.IsOpen)
			{
				__result = false;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[]
		{
			typeof(Character),
			typeof(Character)
		})]
		private static bool IsEnemyPrefix(Character a, Character b, ref bool __result)
		{
			if (!Possession.IsActive)
			{
				return true;
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || ((Object)(object)a != (Object)(object)localPlayer && (Object)(object)b != (Object)(object)localPlayer))
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "AutoPickup")]
		private static bool AutoPickupPrefix()
		{
			return !Possession.IsActive;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(PlayerController), "TakeInput")]
		private static void ControllerTakeInputPostfix(ref bool __result)
		{
			if (MobMenu.IsOpen)
			{
				__result = false;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "SetControls")]
		private static bool SetControlsPrefix(Player __instance, Vector3 movedir, bool attackHold, bool blockHold, bool secondaryAttackHold, bool jump, bool run)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (!Possession.IsActive || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			Possession.Drive(movedir, attackHold, blockHold, secondaryAttackHold, jump, run);
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
		private static void MouseCapturePostfix()
		{
			if (MobMenu.IsOpen)
			{
				ZCursor.LockState = (CursorLockMode)0;
				ZCursor.Show();
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZInput), "GetButton")]
		private static bool GetButtonPrefix(ref bool __result)
		{
			return BlockBool(ref __result);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZInput), "GetButtonDown")]
		private static bool GetButtonDownPrefix(ref bool __result)
		{
			return BlockBool(ref __result);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZInput), "GetButtonUp")]
		private static bool GetButtonUpPrefix(ref bool __result)
		{
			return BlockBool(ref __result);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZInput), "GetKey", new Type[]
		{
			typeof(KeyCode),
			typeof(bool)
		})]
		private static bool GetKeyPrefix(ref bool __result)
		{
			return BlockBool(ref __result);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZInput), "GetKeyDown", new Type[]
		{
			typeof(KeyCode),
			typeof(bool)
		})]
		private static bool GetKeyDownPrefix(ref bool __result)
		{
			return BlockBool(ref __result);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZInput), "GetKeyUp", new Type[]
		{
			typeof(KeyCode),
			typeof(bool)
		})]
		private static bool GetKeyUpPrefix(ref bool __result)
		{
			return BlockBool(ref __result);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZInput), "GetMouseScrollWheel")]
		private static bool ScrollPrefix(ref float __result)
		{
			if (!MobMenu.IsOpen)
			{
				return true;
			}
			__result = 0f;
			return false;
		}

		private static bool BlockBool(ref bool result)
		{
			if (!MobMenu.IsOpen)
			{
				return true;
			}
			result = false;
			return false;
		}
	}
	[HarmonyPatch]
	internal static class MapPatches
	{
		internal static bool WantedPublic;

		private static bool ForceHidden => MorphModPlugin.HidePlayerOnMap;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ZNet), "SetPublicReferencePosition")]
		private static void SetPublicPrefix(ref bool pub)
		{
			WantedPublic = pub;
			if (ForceHidden)
			{
				pub = false;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ZNet), "IsReferencePositionPublic")]
		private static void IsPublicPostfix(ref bool __result)
		{
			if (ForceHidden)
			{
				__result = WantedPublic;
			}
		}
	}
	internal static class MobMenu
	{
		private enum Tab
		{
			Creatures,
			Despawn,
			Settings
		}

		private enum Filter
		{
			All,
			Bosses,
			Flying,
			Water,
			Critters
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static WindowFunction <0>__DrawWindow;
		}

		private const int WindowId = 6948321;

		private const float Width = 820f;

		private const float Height = 700f;

		private const float ListWidth = 476f;

		private const float DetailWidth = 304f;

		private const float RowHeight = 54f;

		private const int PreviewWidth = 280;

		private const int PreviewHeight = 250;

		private static readonly string[] FilterNames = new string[5] { "All", "Bosses", "Flying", "Water", "Critters" };

		private static Rect _window = new Rect(60f, 60f, 820f, 700f);

		private static Vector2 _scroll;

		private static Vector2 _detailScroll;

		private static string _search = "";

		private static Tab _tab;

		private static Filter _filter;

		private static MobEntry _selected;

		private static int _stars;

		private static int _count = 1;

		private static float _radius = 30f;

		private static bool _includeTamed;

		private static bool _includeBosses;

		private static readonly List<ZDOID> Spawned = new List<ZDOID>();

		private static readonly List<MobEntry> Visible = new List<MobEntry>();

		private static GUIStyle _centerHint;

		private static GUIStyle _countLabel;

		internal static bool IsOpen { get; private set; }

		private static int Level
		{
			get
			{
				if (_selected == null || !_selected.Has(MobTraits.Critter))
				{
					return _stars + 1;
				}
				return 1;
			}
		}

		internal static void Toggle()
		{
			IsOpen = !IsOpen;
			if (!IsOpen)
			{
				GUI.FocusControl((string)null);
			}
		}

		internal static void Draw()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Invalid comparison between Unknown and I4
			//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_00b4: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: 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_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: Expected O, but got Unknown
			if (!IsOpen)
			{
				return;
			}
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !MorphModPlugin.IsAdmin())
			{
				IsOpen = false;
				return;
			}
			Event current = Event.current;
			if ((int)current.type == 4 && (int)current.keyCode == 27)
			{
				IsOpen = false;
				current.Use();
				return;
			}
			Styles.Ensure();
			if (_centerHint == null)
			{
				_centerHint = new GUIStyle(Styles.Hint)
				{
					alignment = (TextAnchor)4
				};
				_countLabel = new GUIStyle(Styles.Label)
				{
					alignment = (TextAnchor)4,
					fontStyle = (FontStyle)1
				};
			}
			GUISkin skin = GUI.skin;
			GUI.skin = Styles.Skin;
			float num = Mathf.Max(1f, (float)Screen.height / 1080f);
			Matrix4x4 matrix = GUI.matrix;
			GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(num, num, 1f));
			((Rect)(ref _window)).width = 820f;
			((Rect)(ref _window)).height = 700f;
			Rect window = _window;
			object obj = <>O.<0>__DrawWindow;
			if (obj == null)
			{
				WindowFunction val = DrawWindow;
				<>O.<0>__DrawWindow = val;
				obj = (object)val;
			}
			_window = GUILayout.Window(6948321, window, (WindowFunction)obj, "", Styles.Window, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(820f),
				GUILayout.Height(700f)
			});
			GUI.matrix = matrix;
			GUI.skin = skin;
		}

		private static void DrawWindow(int id)
		{
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			DrawHeader();
			GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(476f),
				GUILayout.ExpandHeight(true)
			});
			switch (_tab)
			{
			case Tab.Creatures:
				DrawCreatures();
				break;
			case Tab.Despawn:
				DrawDespawn(localPlayer);
				break;
			case Tab.Settings:
				DrawSettings();
				break;
			}
			GUILayout.EndVertical();
			GUILayout.Space(12f);
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(304f),
				GUILayout.ExpandHeight(true)
			});
			DrawDetail(localPlayer);
			GUILayout.EndVertical();
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(476f) });
			DrawTabBar();
			GUILayout.EndVertical();
			GUILayout.Space(12f);
			GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(304f) });
			DrawStatusCard();
			GUILayout.EndVertical();
			GUILayout.EndHorizontal();
			GUI.DragWindow(new Rect(0f, 0f, 776f, 40f));
		}

		private static void DrawHeader()
		{
			GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			GUILayout.Label("◈", Styles.TitleIcon, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(22f),
				GUILayout.Height(28f)
			});
			GUILayout.Label("MorphMod", Styles.Title, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(98f),
				GUILayout.Height(28f)
			});
			GUILayout.Label("v2.0.0", Styles.Value, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(44f),
				GUILayout.Height(28f)
			});
			GUILayout.FlexibleSpace();
			if (GUILayout.Button("✕", Styles.IconButton, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(28f),
				GUILayout.Height(28f)
			}))
			{
				IsOpen = false;
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(6f);
		}

		private static void DrawCreatures()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Invalid comparison between Unknown and I4
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			GUI.SetNextControlName("MorphMod_Search");
			_search = GUILayout.TextField(_search ?? "", Array.Empty<GUILayoutOption>());
			if (string.IsNullOrEmpty(_search) && GUI.GetNameOfFocusedControl() != "MorphMod_Search")
			{
				GUI.Label(GUILayoutUtility.GetLastRect(), "Search by name, prefab or trait…", Styles.Placeholder);
			}
			List<MobEntry> mobList = MobUtils.GetMobList();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			for (int i = 0; i < FilterNames.Length; i++)
			{
				Filter filter = (Filter)i;
				if ((filter != Filter.Bosses || MorphModPlugin.AllowBosses.Value) && GUILayout.Button(FilterNames[i] + "  " + CountFor(mobList, filter), (_filter == filter) ? Styles.ChipOn : Styles.Chip, Array.Empty<GUILayoutOption>()))
				{
					_filter = filter;
					_scroll = Vector2.zero;
				}
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.Space(6f);
			string text = (_search ?? "").Trim().ToLowerInvariant();
			Visible.Clear();
			foreach (MobEntry item in mobList)
			{
				if ((text.Length <= 0 || item.SearchKey.Contains(text)) && Matches(item, _filter))
				{
					Visible.Add(item);
				}
			}
			if (_selected == null && Visible.Count > 0)
			{
				Select(Visible[0]);
			}
			_scroll = GUILayout.BeginScrollView(_scroll, false, false, GUIStyle.none, GUI.skin.verticalScrollbar, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			float num = _scroll.y - 54f;
			float num2 = _scroll.y + 700f;
			for (int j = 0; j < Visible.Count; j++)
			{
				Rect rect = GUILayoutUtility.GetRect(10f, 54f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				if ((int)Event.current.type != 8 && !(((Rect)(ref rect)).yMax < num) && !(((Rect)(ref rect)).y > num2))
				{
					DrawMobRow(rect, j + 1, Visible[j]);
				}
			}
			if (Visible.Count == 0)
			{
				GUILayout.Space(40f);
				GUILayout.Label("Nothing found", _centerHint, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUILayout.Label(Visible.Count + " of " + mobList.Count + " creatures", Styles.Hint, Array.Empty<GUILayoutOption>());
		}

		private static void DrawMobRow(Rect row, int index, MobEntry mob)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Invalid comparison between Unknown and I4
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Invalid comparison between Unknown and I4
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			Event current = Event.current;
			bool flag = mob == _selected;
			bool flag2 = ((Rect)(ref row)).Contains(current.mousePosition);
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((Rect)(ref row)).xMax - 72f, ((Rect)(ref row)).y + 13f, 66f, 28f);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(((Rect)(ref val)).x - 60f, ((Rect)(ref row)).y + 13f, 56f, 28f);
			if ((int)current.type == 7)
			{
				if (flag)
				{
					Styles.RowSelected.Draw(row, false, false, false, false);
				}
				else if (flag2)
				{
					Styles.RowHover.Draw(row, false, false, false, false);
				}
				if (mob.IsBoss)
				{
					Styles.BossBar.Draw(new Rect(((Rect)(ref row)).x + 2f, ((Rect)(ref row)).y + 12f, 3f, ((Rect)(ref row)).height - 24f), false, false, false, false);
				}
				else if (mob.Has(MobTraits.Elite))
				{
					Styles.EliteBar.Draw(new Rect(((Rect)(ref row)).x + 2f, ((Rect)(ref row)).y + 12f, 3f, ((Rect)(ref row)).height - 24f), false, false, false, false);
				}
			}
			if (GUI.Button(new Rect(((Rect)(ref row)).x, ((Rect)(ref row)).y, ((Rect)(ref val2)).x - ((Rect)(ref row)).x - 4f, ((Rect)(ref row)).height), GUIContent.none, GUIStyle.none))
			{
				Select(mob);
			}
			GUI.Label(new Rect(((Rect)(ref row)).x + 6f, ((Rect)(ref row)).y, 24f, ((Rect)(ref row)).height), index.ToString(), Styles.RowIndex);
			Rect val3 = default(Rect);
			((Rect)(ref val3))..ctor(((Rect)(ref row)).x + 36f, ((Rect)(ref row)).y + 6f, 42f, 42f);
			if ((int)current.type == 7)
			{
				Styles.ThumbBox.Draw(val3, false, false, false, false);
			}
			Texture thumbnail = MobPreview.GetThumbnail(mob.Prefab, mob.Has(MobTraits.Critter) ? 1 : (Mathf.Min(_stars, mob.MaxStars) + 1));
			if (Object.op_Implicit((Object)(object)thumbnail))
			{
				GUI.DrawTexture(new Rect(((Rect)(ref val3)).x + 3f, ((Rect)(ref val3)).y + 3f, ((Rect)(ref val3)).width - 6f, ((Rect)(ref val3)).height - 6f), thumbnail, (ScaleMode)2, false);
			}
			else
			{
				GUI.Label(val3, "◆", Styles.ThumbEmpty);
			}
			float num = ((Rect)(ref val3)).xMax + 10f;
			float num2 = ((Rect)(ref val2)).x - num - 8f;
			DrawName(new Rect(num, ((Rect)(ref row)).y + 8f, num2, 20f), mob, Styles.RowTitle);
			GUI.Label(new Rect(num, ((Rect)(ref row)).y + 28f, num2, 18f), mob.Subtitle, Styles.RowSub);
			if (GUI.Button(val2, "Spawn", Styles.GhostButton))
			{
				Select(mob);
				SpawnMany(mob, Player.m_localPlayer);
			}
			if (GUI.Button(val, "Become", Styles.AccentButton))
			{
				Select(mob);
				SpawnAndPossess(mob, Player.m_localPlayer);
			}
		}

		private static void DrawName(Rect rect, MobEntry mob, GUIStyle normal)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0061: 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_00d9: 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)
			GUIStyle val = (mob.IsBoss ? Styles.RowTitleBoss : (mob.Has(MobTraits.Elite) ? Styles.RowTitleElite : normal));
			string text = (mob.IsBoss ? "BOSS" : (mob.Has(MobTraits.Elite) ? "ELITE" : null));
			if (text == null)
			{
				GUI.Label(rect, mob.Name, val);
				return;
			}
			float num = Mathf.Min(val.CalcSize(new GUIContent(mob.Name)).x, ((Rect)(ref rect)).width - 50f);
			GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, num, ((Rect)(ref rect)).height), mob.Name, val);
			GUI.Label(new Rect(((Rect)(ref rect)).x + num + 6f, ((Rect)(ref rect)).y + (((Rect)(ref rect)).height - 15f) * 0.5f, 42f, 15f), text, mob.IsBoss ? Styles.BossBadge : Styles.EliteBadge);
		}

		private static void Select(MobEntry mob)
		{
			//IL_000f: 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)
			if (_selected != mob)
			{
				_selected = mob;
				_detailScroll = Vector2.zero;
				if (mob != null)
				{
					_stars = Mathf.Min(_stars, mob.MaxStars);
				}
			}
		}

		private static bool Matches(MobEntry mob, Filter filter)
		{
			return filter switch
			{
				Filter.Bosses => mob.IsBoss, 
				Filter.Flying => mob.Has(MobTraits.Flies), 
				Filter.Water => mob.Has(MobTraits.Water), 
				Filter.Critters => mob.Has(MobTraits.Critter), 
				_ => true, 
			};
		}

		private static int CountFor(List<MobEntry> mobs, Filter filter)
		{
			int num = 0;
			foreach (MobEntry mob in mobs)
			{
				if (Matches(mob, filter))
				{
					num++;
				}
			}
			return num;
		}

		private static void DrawDetail(Player player)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_007f: Invalid comparison between Unknown and I4
			//IL_0086: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Invalid comparison between Unknown and I4
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Expected O, but got Unknown
			//IL_0152: 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_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(Styles.CardBox, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			MobEntry selected = _selected;
			if (selected == null || !Object.op_Implicit((Object)(object)selected.Prefab))
			{
				GUILayout.FlexibleSpace();
				GUILayout.Label("Pick a creature on the left", _centerHint, Array.Empty<GUILayoutOption>());
				GUILayout.FlexibleSpace();
				GUILayout.EndVertical();
				return;
			}
			Rect rect = GUILayoutUtility.GetRect(280f, 250f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			Event current = Event.current;
			if ((int)current.type == 7)
			{
				Styles.PreviewBox.Draw(rect, false, false, false, false);
			}
			Texture live = MobPreview.GetLive(selected.Prefab, Level, 560, 500);
			if (Object.op_Implicit((Object)(object)live))
			{
				GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 4f, ((Rect)(ref rect)).y + 4f, ((Rect)(ref rect)).width - 8f, ((Rect)(ref rect)).height - 8f), live, (ScaleMode)2, false);
			}
			else
			{
				GUI.Label(rect, "Loading model…", _centerHint);
			}
			GUI.Label(new Rect(((Rect)(ref rect)).x + 10f, ((Rect)(ref rect)).yMax - 22f, ((Rect)(ref rect)).width - 20f, 18f), "drag to rotate", Styles.Hint);
			if ((int)current.type == 3 && ((Rect)(ref rect)).Contains(current.mousePosition))
			{
				MobPreview.Drag(current.delta.x);
				current.Use();
			}
			GUILayout.Space(8f);
			_detailScroll = GUILayout.BeginScrollView(_detailScroll, false, false, GUIStyle.none, GUI.skin.verticalScrollbar, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			GUIStyle val = new GUIStyle(Styles.DetailTitle);
			val.normal.textColor = (selected.IsBoss ? Styles.Boss : (selected.Has(MobTraits.Elite) ? Styles.Elite : Styles.Text));
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(selected.Name, val, Array.Empty<GUILayoutOption>());
			if (selected.IsBoss || selected.Has(MobTraits.Elite))
			{
				GUILayout.Label(selected.IsBoss ? "BOSS" : "ELITE", selected.IsBoss ? Styles.BossBadge : Styles.EliteBadge, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(44f),
					GUILayout.Height(16f)
				});
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.Label(selected.Subtitle, Styles.DetailText, Array.Empty<GUILayoutOption>());
			if (!selected.Has(MobTraits.Critter))
			{
				GUILayout.Space(6f);
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label("STARS", Styles.DetailLabel, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(50f),
					GUILayout.Height(26f)
				});
				for (int i = 1; i <= selected.MaxStars; i++)
				{
					bool flag = _stars >= i;
					if (GUILayout.Button(flag ? "★" : "☆", flag ? Styles.StarOn : Styles.StarOff, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(24f),
						GUILayout.Height(26f)
					}))
					{
						_stars = ((_stars == i) ? (i - 1) : i);
					}
				}
				GUILayout.FlexibleSpace();
				GUILayout.Label("Level " + Level, Styles.Value, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) });
				GUILayout.EndHorizontal();
				if (selected.BaseHealth > 0f)
				{
					StatLine("Health", Mathf.RoundToInt(selected.BaseHealth * (float)Level).ToString("N0"));
					StatLine("Damage", "×" + (1f + (float)(Level - 1) * 0.5f).ToString("0.0#"));
				}
				if (!string.IsNullOrEmpty(selected.AttackNames))
				{
					GUILayout.Space(6f);
					GUILayout.Label("ATTACKS", Styles.DetailLabel, Array.Empty<GUILayoutOption>());
					GUILayout.Label(selected.AttackNames, Styles.DetailText, Array.Empty<GUILayoutOption>());
				}
			}
			GUILayout.EndScrollView();
			GUILayout.Space(6f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("AMOUNT", Styles.DetailLabel, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(60f),
				GUILayout.Height(28f)
			});
			if (GUILayout.Button("−", Styles.GhostButton, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(30f),
				GUILayout.Height(28f)
			}))
			{
				_count = Mathf.Max(1, _count - 1);
			}
			GUILayout.Label(_count.ToString(), _countLabel, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(30f),
				GUILayout.Height(28f)
			});
			if (GUILayout.Button("+", Styles.GhostButton, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(30f),
				GUILayout.Height(28f)
			}))
			{
				_count = Mathf.Min(20, _count + 1);
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button((_count > 1) ? ("Spawn ×" + _count) : "Spawn", Styles.GhostButton, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(36f) }))
			{
				SpawnMany(selected, player);
			}
			if (GUILayout.Button("Become", Styles.AccentButton, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(36f) }))
			{
				SpawnAndPossess(selected, player);
			}
			GUILayout.EndHorizontal();
			GUILayout.EndVertical();
		}

		private static void StatLine(string label, string value)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(label, Styles.DetailText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			GUILayout.FlexibleSpace();
			GUILayout.Label(value, Styles.Label, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
		}

		private static void DrawDespawn(Player player)
		{
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("IN SIGHT", Styles.Section, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Despawn the creature I'm looking at", Styles.DangerButton, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) }))
			{
				GameObject val = MobUtils.FindLookTarget(MorphModPlugin.PossessTargetRange.Value);
				if (Object.op_Implicit((Object)(object)val) && !Possession.IsPossessed(val))
				{
					MorphModPlugin.Message("Despawned: " + MobUtils.DisplayName(val));
					MobUtils.Despawn(val);
				}
				else
				{
					MorphModPlugin.Message("No creature in sight");
				}
			}
			GUILayout.Label("AROUND ME", Styles.Section, Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical(Styles.CardBox, Array.Empty<GUILayoutOption>());
			_radius = Styles.Slider("Radius", Mathf.RoundToInt(_radius) + " m", _radius, 5f, 150f);
			_includeTamed = Styles.Switch(_includeTamed, "Include tamed creatures");
			_includeBosses = Styles.Switch(_includeBosses, "Include bosses");
			GUILayout.EndVertical();
			List<GameObject> mobsInRadius = MobUtils.GetMobsInRadius(((Component)player).transform.position, _radius, _includeTamed, _includeBosses);
			if (GUILayout.Button("Despawn all in radius  (" + mobsInRadius.Count + ")", Styles.DangerButton, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) }))
			{
				foreach (GameObject item in mobsInRadius)
				{
					MobUtils.Despawn(item);
				}
				MorphModPlugin.Message("Despawned creatures: " + mobsInRadius.Count);
			}
			GUILayout.Label("MINE", Styles.Section, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Despawn everything I spawned  (" + Spawned.Count + ")", Styles.DangerButton, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(34f) }))
			{
				DespawnMine();
			}
			GUILayout.FlexibleSpace();
		}

		private static void DrawSettings()
		{
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("POSSESSION", Styles.Section, Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical(Styles.CardBox, Array.Empty<GUILayoutOption>());
			MorphModPlugin.PossessFightMonsters.Value = Styles.Switch(MorphModPlugin.PossessFightMonsters.Value, "Fight monsters instead of players");
			MorphModPlugin.StayInvisibleAfterPossession.Value = Styles.Switch(MorphModPlugin.StayInvisibleAfterPossession.Value, "Stay invisible after possession");
			MorphModPlugin.HideFromMap.Value = Styles.Switch(MorphModPlugin.HideFromMap.Value, "Hide from the map while invisible");
			GUILayout.EndVertical();
			GUILayout.Label("BOSSES", Styles.Section, Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical(Styles.CardBox, Array.Empty<GUILayoutOption>());
			MorphModPlugin.AllowBosses.Value = Styles.Switch(MorphModPlugin.AllowBosses.Value, "Allow bosses");
			MorphModPlugin.RespectAttackConditions.Value = Styles.Switch(MorphModPlugin.RespectAttackConditions.Value, "Vanilla attack rules (phases, flight, water)");
			float value = MorphModPlugin.AttackCooldownScale.Value;
			value = Styles.Slider("Attack cooldowns", (value <= 0f) ? "off" : ("×" + value.ToString("0.0")), value, 0f, 2f);
			MorphModPlugin.AttackCooldownScale.Value = Mathf.Round(value * 10f) / 10f;
			float value2 = MorphModPlugin.AimAssistAngle.Value;
			value2 = Styles.Slider("Aim assist", (value2 <= 0f) ? "off" : (Mathf.RoundToInt(value2) + "°"), value2, 0f, 30f);
			MorphModPlugin.AimAssistAngle.Value = Mathf.Round(value2);
			GUILayout.EndVertical();
			GUILayout.FlexibleSpace();
			GUILayout.Label(((object)MorphModPlugin.MenuKey.Value/*cast due to .constrained prefix*/).ToString() + " or Esc closes the menu  ·  " + ((object)MorphModPlugin.PossessKey.Value/*cast due to .constrained prefix*/).ToString() + " possesses / leaves", Styles.Hint, Array.Empty<GUILayoutOption>());
		}

		private static void DrawStatusCard()
		{
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(Styles.CardBox, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(50f) });
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			Character mob = Possession.Mob;
			if (Possession.IsActive && Object.op_Implicit((Object)(object)Possession.Body))
			{
				string text = MobUtils.DisplayName(Possession.Body);
				GUILayout.Label((Object.op_Implicit((Object)(object)mob) && mob.IsBoss()) ? ("<color=#FF4D5E>" + text + "</color>") : text, Styles.StatusTitle, Array.Empty<GUILayoutOption>());
				GUILayout.Label(Object.op_Implicit((Object)(object)mob) ? ("HP " + Mathf.CeilToInt(mob.GetHealth()).ToString("N0") + " / " + Mathf.CeilToInt(mob.GetMaxHealth()).ToString("N0") + "  ·  " + Mathf.RoundToInt(mob.GetHealthPercentage() * 100f) + "%") : "critter", Styles.StatusSub, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label("<color=#A6A6B0>Not possessing</color>", Styles.StatusTitle, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Look at a creature, press " + ((object)MorphModPlugin.PossessKey.Value/*cast due to .constrained prefix*/).ToString(), Styles.StatusSub, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndVertical();
			GUILayout.FlexibleSpace();
			if (Possession.IsActive)
			{
				if (GUILayout.Button("Leave", Styles.DangerButton, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(72f),
					GUILayout.Height(32f)
				}))
				{
					Possession.Stop();
				}
			}
			else if (GUILayout.Button("Possess", Styles.AccentButton, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(72f),
				GUILayout.Height(32f)
			}))
			{
				GameObject val = MobUtils.FindLookTarget(MorphModPlugin.PossessTargetRange.Value);
				if (Object.op_Implicit((Object)(object)val))
				{
					Possession.Start(val, despawnOnExit: false);
				}
				else
				{
					MorphModPlugin.Message("No creature in sight");
				}
			}
			GUILayout.EndHorizontal();
		}

		private static void DrawTabBar()
		{
			GUILayout.BeginHorizontal(Styles.CardBox, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(50f) });
			DrawTab(Tab.Creatures, "◆", "Creatures");
			DrawTab(Tab.Despawn, "✖", "Despawn");
			DrawTab(Tab.Settings, "≡", "Settings");
			GUILayout.EndHorizontal();
		}

		private static void DrawTab(Tab tab, string icon, string label)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_0045: Invalid comparison between Unknown and I4
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = GUILayoutUtility.GetRect(10f, 38f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			bool flag = _tab == tab;
			bool flag2 = ((Rect)(ref rect)).Contains(Event.current.mousePosition);
			if ((int)Event.current.type == 7 && flag2 && !flag)
			{
				Styles.RowHover.Draw(rect, false, false, false, false);
			}
			GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 22f), icon, flag ? Styles.TabIconOn : Styles.TabIcon);
			GUI.Label(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y + 20f, ((Rect)(ref rect)).width, 16f), label, flag ? Styles.TabLabelOn : Styles.TabLabel);
			if (GUI.Button(rect, GUIContent.none, GUIStyle.none))
			{
				_tab = tab;
				GUI.FocusControl((string)null);
			}
		}

		private static Vector3 SpawnPoint(Player player, GameObject prefab)
		{
			//IL_002a: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			Character component = prefab.GetComponent<Character>();
			float num = ((Object.op_Implicit((Object)(object)component) && component.m_boss) ? 10f : 3f);
			Vector3 val = ((Component)player).transform.position + ((Component)player).transform.forward * num + Vector3.up;
			ZoneSystem instance = ZoneSystem.instance;
			if (!Object.op_Implicit((Object)(object)instance))
			{
				return val;
			}
			if (Object.op_Implicit((Object)(object)prefab.GetComponent<Fish>()))
			{
				float num3 = default(float);
				for (float num2 = 3f; num2 <= 30f; num2 += 3f)
				{
					Vector3 val2 = ((Component)player).transform.position + ((Component)player).transform.forward * num2;
					if (instance.GetSolidHeight(val2, ref num3, 1000) && num3 < instance.m_waterLevel - 1f)
					{
						val2.y = Mathf.Max(num3 + 0.3f, instance.m_waterLevel - 0.8f);
						return val2;
					}
				}
				MorphModPlugin.Message("No water in front of you, the fish spawned on land");
			}
			else if (Object.op_Implicit((Object)(object)prefab.GetComponent<RandomFlyingBird>()))
			{
				val += Vector3.up * 2f;
			}
			return val;
		}

		private static void SpawnMany(MobEntry mob, Player player)
		{
			//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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			if (Object.op_Implicit((Object)(object)player))
			{
				Vector3 val = SpawnPoint(player, mob.Prefab);
				float num = ((_count == 1) ? 0f : (1.5f + (float)_count * 0.25f));
				for (int i = 0; i < _count; i++)
				{
					Vector2 val2 = Random.insideUnitCircle * num;
					Remember(MobUtils.Spawn(mob.Prefab, val + new Vector3(val2.x, 0f, val2.y), Level));
				}
				MorphModPlugin.Message("Spawned: " + mob.Name + StarsText() + ((_count > 1) ? (" ×" + _count) : ""));
			}
		}

		private static void SpawnAndPossess(MobEntry mob, Player player)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)player))
			{
				GameObject val = MobUtils.Spawn(mob.Prefab, SpawnPoint(player, mob.Prefab), Level);
				if (Object.op_Implicit((Object)(object)val))
				{
					Possession.Start(val, despawnOnExit: true);
					IsOpen = false;
				}
			}
		}

		private static string StarsText()
		{
			if (Level <= 1)
			{
				return "";
			}
			return " " + new string('★', Level - 1);
		}

		private static void Remember(GameObject go)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)go))
			{
				ZNetView component = go.GetComponent<ZNetView>();
				if (Object.op_Implicit((Object)(object)component) && component.IsValid())
				{
					Spawned.Add(component.GetZDO().m_uid);
				}
			}
		}

		private static void DespawnMine()
		{
			//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_007a: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (ZDOID item in Spawned)
			{
				GameObject val = (Object.op_Implicit((Object)(object)ZNetScene.instance) ? ZNetScene.instance.FindInstance(item) : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					if (!Possession.IsPossessed(val))
					{
						ZNetView component = val.GetComponent<ZNetView>();
						if (Object.op_Implicit((Object)(object)component) && component.IsValid())
						{
							MobUtils.Despawn(val);
							num++;
						}
					}
				}
				else
				{
					ZDO val2 = ((ZDOMan.instance != null) ? ZDOMan.instance.GetZDO(item) : null);
					if (val2 != null)
					{
						val2.SetOwner(ZDOMan.GetSessionID());
						ZDOMan.instance.DestroyZDO(val2);
						num++;
					}
				}
			}
			Spawned.Clear();
			MorphModPlugin.Message("Despawned my creatures: " + num);
		}
	}
	internal static class MobPreview
	{
		private const int ThumbSize = 96;

		private const float Fov = 26f;

		private static readonly Vector3 StagePosition = new Vector3(0f, 9000f, 0f);

		private static readonly Vector3 ThumbStagePosition = new Vector3(400f, 9000f, 0f);

		private static int _layer = -1;

		private static Camera _camera;

		private static GameObject _rig;

		private static readonly Dictionary<string, RenderTexture> Thumbs = new Dictionary<string, RenderTexture>();

		private static readonly Queue<KeyValuePair<string, GameObject>> Pending = new Queue<KeyValuePair<string, GameObject>>();

		private static readonly HashSet<string> Queued = new HashSet<string>();

		private static readonly HashSet<string> Failed = new HashSet<string>();

		private static readonly List<Material> CreatedMaterials = new List<Material>();

		private static GameObject _liveModel;

		private static GameObject _livePrefab;

		private static int _liveLevel;

		private static float _liveRadius;

		private static Vector3 _liveCenter;

		private static RenderTexture _liveTexture;

		private static float _yaw = -30f;

		private static float _lastDrag = -10f;

		internal static Texture GetThumbnail(GameObject prefab, int level)
		{
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return null;
			}
			string text = ((Object)prefab).name + "#" + level;
			if (Thumbs.TryGetValue(text, out var value) && Object.op_Implicit((Object)(object)value) && value.IsCreated())
			{
				return (Texture)(object)value;
			}
			if (Failed.Contains(text) || Queued.Contains(text))
			{
				return null;
			}
			Queued.Add(text);
			Pending.Enqueue(new KeyValuePair<string, GameObject>(text, prefab));
			return null;
		}

		internal static Texture GetLive(GameObject prefab, int level, int width, int height)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)prefab) || Failed.Contains(((Object)prefab).name + "#" + level))
			{
				return null;
			}
			if ((Object)(object)_livePrefab != (Object)(object)prefab || _liveLevel != level || !Object.op_Implicit((Object)(object)_liveModel))
			{
				DestroyLive();
				_livePrefab = prefab;
				_liveLevel = level;
				_liveModel = Build(prefab, level, StagePosition, out _liveCenter, out _liveRadius);
				if (!Object.op_Implicit((Object)(object)_liveModel))
				{
					Failed.Add(((Object)prefab).name + "#" + level);
				}
			}
			if (!Object.op_Implicit((Object)(object)_liveTexture) || ((Texture)_liveTexture).width != width || ((Texture)_liveTexture).height != height)
			{
				ReleaseTexture(ref _liveTexture);
				_liveTexture = NewTexture(width, height);
			}
			if (!Object.op_Implicit((Object)(object)_liveModel))
			{
				return null;
			}
			return (Texture)(object)_liveTexture;
		}

		internal static void Drag(float deltaX)
		{
			_yaw -= deltaX * 0.6f;
			_lastDrag = Time.unscaledTime;
		}

		internal static void Update()
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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)
			if (!MobMenu.IsOpen)
			{
				DestroyLive();
				if (Pending.Count > 0)
				{
					ClearQueue();
				}
				return;
			}
			if (Pending.Count > 0)
			{
				KeyValuePair<string, GameObject> keyValuePair = Pending.Dequeue();
				Queued.Remove(keyValuePair.Key);
				RenderThumbnail(keyValuePair.Key, keyValuePair.Value);
			}
			if (Object.op_Implicit((Object)(object)_liveModel) && Object.op_Implicit((Object)(object)_liveTexture))
			{
				if (Time.unscaledTime - _lastDrag > 2f)
				{
					_yaw += Time.unscaledDeltaTime * 20f;
				}
				_liveModel.transform.rotation = Quaternion.Euler(0f, _yaw, 0f);
				Render(_liveModel, _liveCenter, _liveRadius, _liveTexture, Styles.PreviewBackground);
			}
		}

		internal static void ReleaseAll()
		{
			DestroyLive();
			ClearQueue();
			foreach (RenderTexture value in Thumbs.Values)
			{
				if (Object.op_Implicit((Object)(object)value))
				{
					value.Release();
					Object.Destroy((Object)(object)value);
				}
			}
			Thumbs.Clear();
			Failed.Clear();
			ReleaseTexture(ref _liveTexture);
			foreach (Material createdMaterial in CreatedMaterials)
			{
				if (Object.op_Implicit((Object)(object)createdMaterial))
				{
					Object.Destroy((Object)(object)createdMaterial);
				}
			}
			CreatedMaterials.Clear();
			if (Object.op_Implicit((Object)(object)_rig))
			{
				Object.Destroy((Object)(object)_rig);
			}
			_rig = null;
			_camera = null;
		}

		private static void ClearQueue()
		{
			Pending.Clear();
			Queued.Clear();
		}

		private static void DestroyLive()
		{
			if (Object.op_Implicit((Object)(object)_liveModel))
			{
				Object.Destroy((Object)(object)_liveModel);
			}
			_liveModel = null;
			_livePrefab = null;
		}

		private static void RenderThumbnail(string key, GameObject prefab)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return;
			}
			int level = int.Parse(key.Substring(key.LastIndexOf('#') + 1));
			Vector3 center;
			float radius;
			GameObject val = Build(prefab, level, ThumbStagePosition, out center, out radius);
			if (!Object.op_Implicit((Object)(object)val))
			{
				Failed.Add(key);
				return;
			}
			val.transform.rotation = Quaternion.Euler(0f, -30f, 0f);
			RenderTexture val2 = NewTexture(96, 96);
			Render(val, center, radius, val2, Styles.ThumbBackground);
			Object.DestroyImmediate((Object)(object)val);
			if (Thumbs.TryGetValue(key, out var value) && Object.op_Implicit((Object)(object)value))
			{
				value.Release();
				Object.Destroy((Object)(object)value);
			}
			Thumbs[key] = val2;
		}

		private static bool EnsureRig()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_0070: 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_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: 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_01ba: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)_camera))
			{
				return true;
			}
			if (_layer < 0)
			{
				int num = 31;
				while (num >= 8 && _layer < 0)
				{
					if (string.IsNullOrEmpty(LayerMask.LayerToName(num)))
					{
						_layer = num;
					}
					num--;
				}
				if (_layer < 0)
				{
					_layer = 31;
				}
			}
			_rig = new GameObject("MorphMod_PreviewRig");
			Object.DontDestroyOnLoad((Object)(object)_rig);
			_rig.transform.position = StagePosition;
			_camera = _rig.AddComponent<Camera>();
			((Behaviour)_camera).enabled = false;
			_camera.cullingMask = 1 << _layer;
			_camera.clearFlags = (CameraClearFlags)2;
			_camera.backgroundColor = new Color(0f, 0f, 0f, 0f);
			_camera.fieldOfView = 26f;
			_camera.nearClipPlane = 0.05f;
			_camera.farClipPlane = 1000f;
			_camera.allowHDR = false;
			_camera.allowMSAA = true;
			_camera.useOcclusionCulling = false;
			AddLight("Key", Quaternion.Euler(35f, -35f, 0f), new Color(1f, 0.96f, 0.9f), 1.15f);
			AddLight("Fill", Quaternion.Euler(15f, 150f, 0f), new Color(0.75f, 0.8f, 1f), 0.45f);
			AddLight("Rim", Quaternion.Euler(-10f, 180f, 0f), new Color(0.95f, 0.6f, 1f), 0.35f);
			return true;
		}

		private static void AddLight(string name, Quaternion rotation, Color color, float intensity)
		{
			//IL_000b: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("MorphMod_Preview" + name);
			val.transform.SetParent(_rig.transform, false);
			val.transform.rotation = rotation;
			Light obj = val.AddComponent<Light>();
			obj.type = (LightType)1;
			obj.color = color;
			obj.intensity = intensity;
			obj.shadows = (LightShadows)0;
			obj.cullingMask = 1 << _layer;
		}

		private static RenderTexture NewTexture(int width, int height)
		{
			//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_0011: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			RenderTexture val = new RenderTexture(width, height, 24, (RenderTextureFormat)0)
			{
				antiAliasing = 4,
				hideFlags = (HideFlags)61,
				name = "MorphMod_Preview"
			};
			val.Create();
			return val;
		}

		private static void ReleaseTexture(ref RenderTexture tex)
		{
			if (Object.op_Implicit((Object)(object)tex))
			{
				tex.Release();
				Object.Destroy((Object)(object)tex);
			}
			tex = null;
		}

		private static void Render(GameObject model, Vector3 center, float radius, RenderTexture target, Color background)
		{
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0081: 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_008f: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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_00f9: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			if (!EnsureRig() || !Object.op_Implicit((Object)(object)target))
			{
				return;
			}
			float num = (float)((Texture)target).width / (float)((Texture)target).height;
			float num2 = 0.2268928f;
			float num3 = radius / Mathf.Sin(num2);
			float num4 = radius / Mathf.Sin(Mathf.Atan(Mathf.Tan(num2) * num));
			float num5 = Mathf.Max(num3, num4) * 1.02f;
			Vector3 val = model.transform.position + center;
			Vector3 val2 = Quaternion.Euler(12f, 180f, 0f) * Vector3.forward;
			((Component)_camera).transform.position = val - val2 * num5;
			((Component)_camera).transform.rotation = Quaternion.LookRotation(val2);
			_camera.farClipPlane = num5 + radius * 4f + 10f;
			_camera.aspect = num;
			_camera.targetTexture = target;
			_camera.backgroundColor = background;
			bool fog = RenderSettings.fog;
			AmbientMode ambientMode = RenderSettings.ambientMode;
			Color ambientLight = RenderSettings.ambientLight;
			float ambientIntensity = RenderSettings.ambientIntensity;
			try
			{
				RenderSettings.fog = false;
				RenderSettings.ambientMode = (AmbientMode)3;
				RenderSettings.ambientLight = new Color(0.42f, 0.42f, 0.46f);
				RenderSettings.ambientIntensity = 1f;
				_camera.Render();
			}
			catch (Exception ex)
			{
				MorphModPlugin.LogWarning("Preview render failed: " + ex.Message);
			}
			finally
			{
				RenderSettings.fog = fog;
				RenderSettings.ambientMode = ambientMode;
				RenderSettings.ambientLight = ambientLight;
				RenderSettings.ambientIntensity = ambientIntensity;
				_camera.targetTexture = null;
			}
		}

		private static GameObject Build(GameObject prefab, int level, Vector3 position, out Vector3 center, out float radius)
		{
			//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)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			center = Vector3.up;
			radius = 1f;
			if (!EnsureRig())
			{
				return null;
			}
			GameObject val = new GameObject("MorphMod_PreviewModel");
			val.SetActive(false);
			try
			{
				GameObject obj = Object.Instantiate<GameObject>(prefab, val.transform, false);
				obj.transform.localPosition = Vector3.zero;
				obj.transform.localRotation = Quaternion.identity;
				ApplyLevelLook(obj, level);
				Strip(obj);
				SetLayer(val.transform, _layer);
				val.transform.position = position;
				val.SetActive(true);
				Animator[] componentsInChildren = val.GetComponentsInChildren<Animator>();
				foreach (Animator obj2 in componentsInChildren)
				{
					obj2.fireEvents = false;
					obj2.cullingMode = (AnimatorCullingMode)0;
					obj2.Update(0f);
				}
				if (!MeasureBounds(val, out var bounds))
				{
					Object.DestroyImmediate((Object)(object)val);
					return null;
				}
				center = ((Bounds)(ref bounds)).center - val.transform.position;
				Vector3 extents = ((Bounds)(ref bounds)).extents;
				radius = Mathf.Max(0.2f, ((Vector3)(ref extents)).magnitude);
				return val;
			}
			catch (Exception ex)
			{
				MorphModPlugin.LogWarning("Preview of " + ((Object)prefab).name + " failed: " + ex.Message);
				Object.DestroyImmediate((Object)(object)val);
				return null;
			}
		}

		private static void ApplyLevelLook(GameObject clone, int level)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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)
			//IL_0095: Expected O, but got Unknown
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			LevelEffects componentInChildren = clone.GetComponentInChildren<LevelEffects>(true);
			if (!Object.op_Implicit((Object)(object)componentInChildren) || level <= 1 || componentInChildren.m_levelSetups == null || componentInChildren.m_levelSetups.Count < level - 1)
			{
				return;
			}
			LevelSetup val = componentInChildren.m_levelSetups[level - 2];
			((Component)componentInChildren).transform.localScale = Vector3.one * val.m_scale;
			if (Object.op_Implicit((Object)(object)componentInChildren.m_mainRender))
			{
				Material[] sharedMaterials = componentInChildren.m_mainRender.sharedMaterials;
				if (sharedMaterials.Length != 0 && Object.op_Implicit((Object)(object)sharedMaterials[0]))
				{
					Material val2 = new Material(sharedMaterials[0])
					{
						hideFlags = (HideFlags)61
					};
					val2.SetFloat("_Hue", val.m_hue);
					val2.SetFloat("_Saturation", val.m_saturation);
					val2.SetFloat("_Value", val.m_value);
					if (val.m_setEmissiveColor)
					{
						val2.SetColor("_EmissionColor", val.m_emissiveColor);
					}
					sharedMaterials[0] = val2;
					componentInChildren.m_mainRender.sharedMaterials = sharedMaterials;
					CreatedMaterials.Add(val2);
				}
			}
			if (Object.op_Implicit((Object)(object)componentInChildren.m_baseEnableObject))
			{
				componentInChildren.m_baseEnableObject.SetActive(false);
			}
			if (Object.op_Implicit((Object)(object)val.m_enableObject))
			{
				val.m_enableObject.SetActive(true);
			}
		}

		private static void Strip(GameObject clone)
		{
			//IL_00a2: 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_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Expected O, but got Unknown
			Rigidbody[] componentsInChildren = clone.GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody obj in componentsInChildren)
			{
				obj.isKinematic = true;
				obj.useGravity = false;
			}
			Collider[] componentsInChildren2 = clone.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				componentsInChildren2[i].enabled = false;
			}
			Light[] componentsInChildren3 = clone.GetComponentsInChildren<Light>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				((Behaviour)componentsInChildren3[i]).enabled = false;
			}
			AudioSource[] componentsInChildren4 = clone.GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource obj2 in componentsInChildren4)
			{
				obj2.playOnAwake = false;
				((Behaviour)obj2).enabled = false;
			}
			ParticleSystem[] componentsInChildren5 = clone.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem obj3 in componentsInChildren5)
			{
				MainModule main = obj3.main;
				((MainModule)(ref main)).playOnAwake = false;
				Renderer component = ((Component)obj3).GetComponent<Renderer>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.enabled = false;
				}
			}
			TrailRenderer[] componentsInChildren6 = clone.GetComponentsInChildren<TrailRenderer>(true);
			for (int i = 0; i < componentsInChildren6.Length; i++)
			{
				((Renderer)componentsInChildren6[i]).enabled = false;
			}
			LineRenderer[] componentsInChildren7 = clone.GetComponentsInChildren<LineRenderer>(true);
			for (int i = 0; i < componentsInChildren7.Length; i++)
			{
				((Renderer)componentsInChildren7[i]).enabled = false;
			}
			List<MonoBehaviour> list = new List<MonoBehaviour>(clone.GetComponentsInChildren<MonoBehaviour>(true));
			for (int j = 0; j < 8; j++)
			{
				if (list.Count <= 0)
				{
					break;
				}
				HashSet<Type> hashSet = new HashSet<Type>();
				foreach (MonoBehaviour item in list)
				{
					if (!Object.op_Implicit((Object)(object)item))
					{
						continue;
					}
					object[] customAttributes = ((object)item).GetType().GetCustomAttributes(typeof(RequireComponent), inherit: true);
					for (int i = 0; i < customAttributes.Length; i++)
					{
						RequireComponent val = (RequireComponent)customAttributes[i];
						if (val.m_Type0 != null)
						{
							hashSet.Add(val.m_Type0);
						}
						if (val.m_Type1 != null)
						{
							hashSet.Add(val.m_Type1);
						}
						if (val.m_Type2 != null)
						{
							hashSet.Add(val.m_Type2);
						}
					}
				}
				for (int num = list.Count - 1; num >= 0; num--)
				{
					MonoBehaviour val2 = list[num];
					if (!Object.op_Implicit((Object)(object)val2))
					{
						list.RemoveAt(num);
					}
					else if (!IsRequired(((object)val2).GetType(), hashSet))
					{
						Object.DestroyImmediate((Object)(object)val2);
						list.RemoveAt(num);
					}
				}
			}
			foreach (MonoBehaviour item2 in list)
			{
				if (Object.op_Implicit((Object)(object)item2))
				{
					((Behaviour)item2).enabled = false;
				}
			}
		}

		private static bool IsRequired(Type type, HashSet<Type> required)
		{
			foreach (Type item in required)
			{
				if (item.IsAssignableFrom(type))
				{
					return true;
				}
			}
			return false;
		}

		private static void SetLayer(Transform t, int layer)
		{
			((Component)t).gameObject.layer = layer;
			for (int i = 0; i < t.childCount; i++)
			{
				SetLayer(t.GetChild(i), layer);
			}
		}

		private static bool MeasureBounds(GameObject root, out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0093: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			bool flag = false;
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				if (!val.enabled || val is ParticleSystemRenderer || val is TrailRenderer || val is LineRenderer)
				{
					continue;
				}
				SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null);
				if (val2 != null)
				{
					val2.updateWhenOffscreen = true;
				}
				Bounds bounds2 = val.bounds;
				Vector3 size = ((Bounds)(ref bounds2)).size;
				if (((Vector3)(ref size)).sqrMagnitude < 0.0001f)
				{
					continue;
				}
				size = ((Bounds)(ref bounds2)).size;
				if (!(((Vector3)(ref size)).magnitude > 200f))
				{
					if (!flag)
					{
						bounds = bounds2;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(bounds2);
					}
					flag = true;
				}
			}
			return flag;
		}
	}
	[Flags]
	internal enum MobTraits
	{
		None = 0,
		Boss = 1,
		Flies = 2,
		CanLand = 4,
		Water = 8,
		Critter = 0x10,
		Fighter = 0x20,
		Elite = 0x40
	}
	internal class MobEntry
	{
		public GameObject Prefab;

		public string Name;

		public string Subtitle;

		public string SearchKey;

		public MobTraits Traits;

		public int AttackCount;

		public string AttackNames = "";

		public int MaxStars;

		public float BaseHealth;

		public bool IsBoss => (Traits & MobTraits.Boss) != 0;

		public bool Has(MobTraits trait)
		{
			return (Traits & trait) != 0;
		}
	}
	internal static class MobUtils
	{
		private static List<MobEntry> _mobs;

		private static int _mobsPrefabCount = -1;

		private static bool _mobsWithBosses;

		internal static List<MobEntry> GetMobList()
		{
			ZNetScene instance = ZNetScene.instance;
			if (!Object.op_Implicit((Object)(object)instance))
			{
				return new List<MobEntry>();
			}
			if (_mobs != null && _mobsPrefabCount == instance.m_prefabs.Count && _mobsWithBosses == MorphModPlugin.AllowBosses.Value)
			{
				return _mobs;
			}
			_mobsWithBosses = MorphModPlugin.AllowBosses.Value;
			_mobs = new List<MobEntry>();
			_mobsPrefabCount = instance.m_prefabs.Count;
			foreach (GameObject prefab in instance.m_prefabs)
			{
				if (!Object.op_Implicit((Object)(object)prefab))
				{
					continue;
				}
				MobTraits mobTraits = MobTraits.None;
				int attacks = 0;
				string attackNames = "";
				Character component = prefab.GetComponent<Character>();
				Fish component2 = prefab.GetComponent<Fish>();
				string name;
				if (Object.op_Implicit((Object)(object)component))
				{
					if (!IsAllowedMob(component))
					{
						continue;
					}
					name = component.m_name;
					mobTraits = AnalyzeCharacter(component, out attacks, out attackNames);
				}
				else if (Object.op_Implicit((Object)(object)component2))
				{
					name = component2.m_name;
					mobTraits = MobTraits.Water | MobTraits.Critter;
				}
				else
				{
					if (!Object.op_Implicit((Object)(object)prefab.GetComponent<RandomFlyingBird>()))
					{
						continue;
					}
					name = ((Object)prefab).name;
					mobTraits = MobTraits.Flies | MobTraits.CanLand | MobTraits.Critter;
				}
				string text = Localize(name);
				if (!string.IsNullOrEmpty(text) && text.Contains("<color"))
				{
					mobTraits |= MobTraits.Elite;
				}
				text = StripTags(text);
				string text2 = ((string.IsNullOrEmpty(text) || text.StartsWith("$") || text.StartsWith("[")) ? ((Object)prefab).name : text);
				string text3 = DescribeTraits(((Object)prefab).name, mobTraits, attacks);
				_mobs.Add(new MobEntry
				{
					Prefab = prefab,
					Name = text2,
					Subtitle = text3,
					Traits = mobTraits,
					AttackCount = attacks,
					AttackNames = attackNames,
					MaxStars = MaxStarsOf(prefab),
					BaseHealth = (Object.op_Implicit((Object)(object)component) ? component.m_health : 0f),
					SearchKey = (text2 + " " + text3).ToLowerInvariant()
				});
			}
			_mobs.Sort((MobEntry a, MobEntry b) => (SortRank(a) == SortRank(b)) ? string.Compare(a.Name, b.Name, StringComparison.CurrentCultureIgnoreCase) : SortRank(a).CompareTo(SortRank(b)));
			return _mobs;
		}

		private static int SortRank(MobEntry mob)
		{
			if (!mob.IsBoss)
			{
				if (!mob.Has(MobTraits.Elite))
				{
					return 2;
				}
				return 1;
			}
			return 0;
		}

		internal static string StripTags(string text)
		{
			if (!string.IsNullOrEmpty(text))
			{
				return Regex.Replace(text, "<[^>]+>", "").Trim();
			}
			return text;
		}

		private static int MaxStarsOf(GameObject prefab)
		{
			LevelEffects componentInChildren = prefab.GetComponentInChildren<LevelEffects>(true);
			int num = ((Object.op_Implicit((Object)(object)componentInChildren) && componentInChildren.m_levelSetups != null) ? componentInChildren.m_levelSetups.Count : 0);
			return Mathf.Clamp(Mathf.Max(2, num), 0, 5);
		}

		private static MobTraits AnalyzeCharacter(Character character, out int attacks, out string attackNames)
		{
			MobTraits mobTraits = MobTraits.None;
			attacks = 0;
			List<string> list = new List<string>();
			BaseAI component = ((Component)character).GetComponent<BaseAI>();
			bool flag = false;
			Humanoid val = (Humanoid)(object)((character is Humanoid) ? character : null);
			if (val != null)
			{
				foreach (GameObject item in EnumerateItems(val))
				{
					ItemDrop val2 = (Object.op_Implicit((Object)(object)item) ? item.GetComponent<ItemDrop>() : null);
					ItemData val3 = (Object.op_Implicit((Object)(object)val2) ? val2.m_itemData : null);
					if (val3 == null || !val3.IsWeapon() || !val3.HavePrimaryAttack())
					{
						continue;
					}
					if (BossMechanics.TogglesFlight(val3))
					{
						flag = true;
						continue;
					}
					attacks++;
					string text = StripTags(Localize(val3.m_shared.m_name));
					if (string.IsNullOrEmpty(text) || text.StartsWith("$") || text.StartsWith("["))
					{
						text = ((Object)item).name;
					}
					if (!list.Contains(text))
					{
						list.Add(text);
					}
				}
			}
			if (character.m_boss)
			{
				mobTraits |= MobTraits.Boss;
			}
			if (attacks > 0)
			{
				mobTraits |= MobTraits.Fighter;
			}
			if (character.m_flying)
			{
				mobTraits |= MobTraits.Flies;
				if (character.m_boss || flag || (Object.op_Implicit((Object)(object)component) && component.m_randomFly))
				{
					mobTraits |= MobTraits.CanLand;
				}
			}
			else if (flag || (Object.op_Implicit((Object)(object)component) && component.m_randomFly))
			{
				mobTraits |= MobTraits.Flies | MobTraits.CanLand;
			}
			MonsterAI val4 = (MonsterAI)(object)((component is MonsterAI) ? component : null);
			if (val4 != null && val4.m_avoidLand)
			{
				mobTraits |= MobTraits.Water;
			}
			attackNames = string.Join(", ", list.ToArray());
			return mobTraits;
		}

		private static IEnumerable<GameObject> EnumerateItems(Humanoid humanoid)
		{
			HashSet<GameObject> seen = new HashSet<GameObject>();
			GameObject[][] array = new GameObject[3][] { humanoid.m_defaultItems, humanoid.m_randomWeapon, humanoid.m_randomShield };
			GameObject[][] array2 = array;
			foreach (GameObject[] array3 in array2)
			{
				if (array3 == null)
				{
					continue;
				}
				GameObject[] array4 = array3;
				foreach (GameObject val in array4)
				{
					if (Object.op_Implicit((Object)(object)val) && seen.Add(val))
					{
						yield return val;
					}
				}
			}
			if (humanoid.m_randomSets == null)
			{
				yield break;
			}
			ItemSet[] randomSets = humanoid.m_randomSets;
			foreach (ItemSet val2 in randomSets)
			{
				if (val2?.m_items == null)
				{
					continue;
				}
				GameObject[] array4 = val2.m_items;
				foreach (GameObject val3 in array4)
				{
					if (Object.op_Implicit((Object)(object)val3) && seen.Add(val3))
					{
						yield return val3;
					}
				}
			}
		}

		private static string DescribeTraits(string prefabName, MobTraits traits, int attacks)
		{
			List<string> list = new List<string> { prefabName };
			if ((traits & MobTraits.Boss) != MobTraits.None)
			{
				list.Add("boss");
			}
			else if ((traits & MobTraits.Elite) != MobTraits.None)
			{
				list.Add("elite");
			}
			if ((traits & MobTraits.Critter) != MobTraits.None)
			{
				list.Add(((traits & MobTraits.Water) != MobTraits.None) ? "fish" : "bird");
			}
			else
			{
				if ((traits & MobTraits.Flies) != MobTraits.None)
				{
					list.Add(((traits & MobTraits.CanLand) != MobTraits.None) ? "flies · lands" : "always flies");
				}
				if ((traits & MobTraits.Water) != MobTraits.None)
				{
					list.Add("water");
				}
				list.Add((attacks == 1) ? "1 attack" : (attacks + " attacks"));
			}
			return string.Join(" · ", list.ToArray());
		}

		internal static string Localize(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return text;
			}
			if (Localization.instance == null)
			{
				return text;
			}
			return Localization.instance.Localize(text);
		}

		internal static string DisplayName(GameObject body)
		{
			if (!Object.op_Implicit((Object)(object)body))
			{
				return "";
			}
			Character component = body.GetComponent<Character>();
			Fish component2 = body.GetComponent<Fish>();
			string text = StripTags(Object.op_Implicit((Object)(object)component) ? Localize(component.m_name) : (Object.op_Implicit((Object)(object)component2) ? Localize(component2.m_name) : null));
			if (!string.IsNullOrEmpty(text) && !text.StartsWith("$") && !text.StartsWith("["))
			{
				return text;
			}
			return ((Object)body).name.Replace("(Clone)", "").Trim();
		}

		internal static bool IsAllowedMob(Character character)
		{
			if (Object.op_Implicit((Object)(object)character) && !(character is Player))
			{
				if (character.m_boss)
				{
					return MorphModPlugin.AllowBosses.Value;
				}
				return true;
			}
			return false;
		}

		internal static bool IsCritter(GameObject go)
		{
			if (Object.op_Implicit((Object)(object)go))
			{
				if (!Object.op_Implicit((Object)(object)go.GetComponent<Fish>()))
				{
					return Object.op_Implicit((Object)(object)go.GetComponent<RandomFlyingBird>());
				}
				return true;
			}
			return false;
		}

		internal static bool IsValidBody(GameObject go)
		{
			if (!Object.op_Implicit((Object)(object)go))
			{
				return false;
			}
			Character component = go.GetComponent<Character>();
			if (Object.op_Implicit((Object)(object)component))
			{
				if (IsAllowedMob(component))
				{
					return !component.IsDead();
				}
				return false;
			}
			return IsCritter(go);
		}

		internal static GameObject FindLookTarget(float range)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_00f2: 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)
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || !Object.op_Implicit((Object)(object)GameCamera.instance))
			{
				return null;
			}
			Character hoverCreature = localPlayer.GetHoverCreature();
			if (Object.op_Implicit((Object)(object)hoverCreature) && IsValidBody(((Component)hoverCreature).gameObject))
			{
				return ((Component)hoverCreature).gameObject;
			}
			Transform transform = ((Component)GameCamera.instance).transform;
			RaycastHit[] array = Physics.RaycastAll(transform.position, transform.forward, range + 10f, -1, (QueryTriggerInteraction)1);
			Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
			RaycastHit[] array2 = array;
			for (int num = 0; num < array2.Length; num++)
			{
				RaycastHit val = array2[num];
				if (!((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Player>() == (Object)(object)localPlayer))
				{
					Character componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Character>();
					GameObject val2 = (Object.op_Implicit((Object)(object)componentInParent) ? ((Component)componentInParent).gameObject : FindCritterRoot(((Component)((RaycastHit)(ref val)).collider).transform));
					if (!Object.op_Implicit((Object)(object)val2) || Vector3.Distance(((Component)localPlayer).transform.position, val2.transform.position) > range)
					{
						break;
					}
					if (!IsValidBody(val2))
					{
						return null;
					}
					return val2;
				}
			}
			return FindCritterInSight(transform, localPlayer, range);
		}

		private static GameObject FindCritterRoot(Transform t)
		{
			Fish componentInParent = ((Component)t).GetComponentInParent<Fish>();
			if (Object.op_Implicit((Object)(object)componentInParent))
			{
				return ((Component)componentInParent).gameObject;
			}
			RandomFlyingBird componentInParent2 = ((Component)t).GetComponentInParent<RandomFlyingBird>();
			if (!Object.op_Implicit((Object)(object)componentInParent2))
			{
				return null;
			}
			return ((Component)componentInParent2).gameObject;
		}

		private static GameObject FindCritterInSight(Transform cam, Player player, float range)
		{
			//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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			GameObject result = null;
			float num = 6f;
			foreach (MonoBehaviour allCritter in GetAllCritters())
			{
				Vector3 val = ((Component)allCritter).transform.position - cam.position;
				if (!(Vector3.Distance(((Component)player).transform.position, ((Component)allCritter