Decompiled source of AllTameableTamingOverhaul v1.4.12

AllTameable_TamingOverhaul.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using AllTameable;
using AllTameable.AutoFeedAT;
using AllTameable.CLLC;
using AllTameable.DNA;
using AllTameable.Genetics;
using AllTameable.MonMod;
using AllTameable.RPC;
using AllTameable.RRRCoreTameable;
using AllTameable.Trading;
using AllTameable.VikingNPC_AT;
using AutoFeed;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CreatureLevelControl;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using MonsterModifiers;
using MonsterModifiers.Custom_Components;
using RRRCore;
using Settlers.Behaviors;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("AllTameable_TamingOverhaul")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AllTameable_TamingOverhaul")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("db3f13a2-a323-4902-ad30-87a28b8836b6")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
public class CraftingConditions : MonoBehaviour
{
	public GameObject Root;

	public static List<ItemData> ConditionItems = new List<ItemData>();

	public static string[] tamednearby_prefName = new string[2] { "AT_HasTamed_Item", "Tamed Creatures Nearby" };

	[HarmonyPostfix]
	[HarmonyPatch(typeof(Inventory), "CountItems")]
	private static void PostfixCountItems(Inventory __instance, ref int __result, string name, int quality, bool matchWorldLevel)
	{
		if (ConditionItems.Exists((ItemData item) => item.m_shared.m_name == name))
		{
			__result += hasCondition(name, __instance);
		}
	}

	private static int hasCondition(string name, Inventory inv)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		if (name == tamednearby_prefName[1])
		{
			Vector3 position = ((Component)Player.m_localPlayer).transform.position;
			return getTamedCloseto(position, 10f);
		}
		return 0;
	}

	public static int getTamedCloseto(Vector3 center, float maxdist)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		List<Character> allCharacters = Character.GetAllCharacters();
		int num = 0;
		foreach (Character item in allCharacters)
		{
			if (Vector3.Distance(((Component)item).transform.position, center) < maxdist && item.m_tamed && ((Component)item).GetComponent<ZNetView>().IsValid())
			{
				num++;
			}
		}
		return num;
	}

	[HarmonyPrefix]
	[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
	{
		typeof(Recipe),
		typeof(bool),
		typeof(int),
		typeof(int)
	})]
	private static void PostfixHaveRequirementItems(Player __instance)
	{
		bool flag = false;
		if (!__instance.m_knownMaterial.Contains(tamednearby_prefName[1]))
		{
			DBG.blogDebug("Added Tamed Creatures Nearby item");
			__instance.m_knownMaterial.Add(tamednearby_prefName[1]);
			flag = true;
		}
		if (flag)
		{
			__instance.UpdateKnownRecipesList();
		}
	}

	private void Awake()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		Root = new GameObject("CraftingConditions");
		Root.transform.SetParent(Plugin.Root.transform);
		Root.SetActive(false);
	}

	public static void setConditionItems()
	{
		DBG.blogDebug("in setcondtions");
		addHasTamedCondition();
	}

	private static void addHasTamedCondition()
	{
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Expected O, but got Unknown
		CustomItem val = ItemManager.Instance.GetItem(tamednearby_prefName[0]);
		if (val == null)
		{
			DBG.blogDebug("Added Alltame Has TamedItem");
			if (tamednearby_prefName.Length == 0)
			{
				DBG.blogDebug("no prefab name");
				tamednearby_prefName = new string[2] { "AT_HasTamed_Item", "Tamed Creatures Nearby" };
			}
			DBG.blogDebug(tamednearby_prefName[0]);
			if (!Object.op_Implicit((Object)(object)PrefabManager.Instance.GetPrefab("TrophyBoar")))
			{
				DBG.blogDebug("could not find TrophyBoar as prefab");
			}
			else
			{
				DBG.blogDebug("Found TrophyBoar as gameobject");
				val = new CustomItem(tamednearby_prefName[0], "TrophyBoar");
			}
			ItemManager.Instance.AddItem(val);
			DBG.blogDebug("Added item to manager");
			ItemData itemData = val.ItemDrop.m_itemData;
			itemData.m_shared.m_name = tamednearby_prefName[1];
			itemData.m_shared.m_description = "You have tamed creatures nearby";
			DBG.blogDebug("Adding item to conditions");
			ConditionItems.Add(itemData);
			DBG.blogDebug("Added item to conditions");
		}
		else
		{
			DBG.blogDebug("Already had Alltame TamedItem");
		}
		DBG.blogDebug("AddTamedCondition has been added");
	}

	private static void addHasTamedCondition_old()
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		CustomItem item = ItemManager.Instance.GetItem(tamednearby_prefName[0]);
		if (item == null)
		{
			DBG.blogDebug("Added Alltame Has TamedItem");
			item = new CustomItem(tamednearby_prefName[0], "TrophyBoar");
			ItemManager.Instance.AddItem(item);
			ItemData itemData = item.ItemDrop.m_itemData;
			itemData.m_shared.m_name = tamednearby_prefName[1];
			itemData.m_shared.m_description = "You have tamed creatures nearby";
			ConditionItems.Add(itemData);
		}
	}
}
public class UtilAlignUp : MonoBehaviour
{
	private void Start()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		((Component)this).transform.up = Vector3.up;
	}

	private void Update()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		((Component)this).transform.up = Vector3.up;
	}
}
public class ActiveClothMesh : MonoBehaviour
{
	public Mesh clothmesh = new Mesh();

	public Cloth clothref;

	public float roughness = 0.001f;

	private float lastTime = 0f;

	public List<ParticleSystem> partsys;

	private void Start()
	{
		//IL_0099: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)clothref))
		{
			clothref = ((Component)((Component)this).transform.parent).GetComponentInChildren<Cloth>();
		}
		((Object)clothmesh).name = "ClothMesh";
		clothmesh.vertices = clothref.vertices;
		clothmesh.normals = clothref.normals;
		partsys = ((Component)this).gameObject.GetComponentsInChildren<ParticleSystem>().ToList();
		foreach (ParticleSystem partsy in partsys)
		{
			ShapeModule shape = partsy.shape;
			if (!Object.op_Implicit((Object)(object)((ShapeModule)(ref shape)).skinnedMeshRenderer))
			{
				ShapeModule shape2 = partsy.shape;
				((ShapeModule)(ref shape2)).skinnedMeshRenderer = ((Component)this).gameObject.GetComponent<SkinnedMeshRenderer>();
			}
		}
	}

	private void Update()
	{
		if (Time.time - lastTime > roughness)
		{
			if (Object.op_Implicit((Object)(object)clothref))
			{
				clothmesh.vertices = clothref.vertices;
				clothmesh.normals = clothref.normals;
			}
			else
			{
				clothref = ((Component)((Component)this).transform.parent).GetComponentInChildren<Cloth>();
			}
			lastTime = Time.time;
		}
	}
}
public class ActiveClothMesh_old : MonoBehaviour
{
	public Mesh clothmesh = new Mesh();

	public Cloth clothref;

	public SkinnedMeshRenderer skinclothref;

	public float roughness = 0.0001f;

	private float lastTime = 0f;

	public float cycletime = 1f;

	private Vector3 maxAngle = new Vector3(355f, 35f, 0f);

	private Vector3 lastpos = Vector3.zero;

	private Character plr_char;

	private float crch = 1f;

	private void Start()
	{
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		DBG.blogDebug("Creating Mesh");
		clothref = ((Component)((Component)this).transform.parent.Find("WolfCape_cloth")).GetComponent<Cloth>();
		((Object)clothmesh).name = "ClothMesh";
		clothmesh.vertices = clothref.vertices;
		clothmesh.normals = clothref.normals;
		ParticleSystem component = ((Component)this).gameObject.GetComponent<ParticleSystem>();
		if (Object.op_Implicit((Object)(object)component))
		{
			ShapeModule shape = component.shape;
			((ShapeModule)(ref shape)).mesh = clothmesh;
		}
		plr_char = ((Component)((Component)this).transform.root).GetComponent<Character>();
	}

	private void Update()
	{
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)plr_char))
		{
			Character obj = plr_char;
			Player val = (Player)(object)((obj is Player) ? obj : null);
			if ((val.m_crouchToggled | plr_char.IsCrouching()) && crch > 0.05f)
			{
				crch -= 0.1f;
			}
			else if ((!val.m_crouchToggled | !plr_char.IsCrouching()) && crch < 1f)
			{
				crch += 0.1f;
			}
		}
		else
		{
			DBG.blogDebug("setting char");
			plr_char = ((Component)((Component)this).transform.root).GetComponent<Character>();
		}
		if (Object.op_Implicit((Object)(object)clothref))
		{
			clothmesh.vertices = clothref.vertices;
			clothmesh.normals = clothref.normals;
		}
		else
		{
			DBG.blogDebug("set clothref");
			clothref = ((Component)((Component)this).transform.Find("WolfCape_cloth")).GetComponent<Cloth>();
		}
		if (Time.time - lastTime > roughness)
		{
			DBG.blogDebug("Updating pos");
			if (lastpos.x == float.NaN)
			{
				DBG.blogDebug("reset pos = " + ((object)(Vector3)(ref lastpos)).ToString());
				lastpos = ((Component)this).transform.position;
				((Component)this).transform.position = Vector3.zero;
				((Component)this).transform.localPosition = Vector3.zero;
			}
			float num = Vector3.Distance(((Component)this).transform.position - new Vector3(0f, 0f - ((Component)this).transform.position.y), lastpos - new Vector3(0f, 0f - lastpos.y)) / (Time.time - lastTime);
			lastTime = Time.time;
			lastpos = ((Component)this).transform.position;
		}
	}
}
public class UtilColorFade : MonoBehaviour
{
	public float roughness = 0.5f;

	private static float startime;

	private float lastTime = 0f;

	public float cycletime = 1f;

	public string colType = "_Color";

	public Gradient grad = new Gradient();

	public Material mat;

	private void Start()
	{
		startime = Time.time + Random.Range(0f - cycletime, cycletime);
	}

	private void Update()
	{
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		if (Time.time - lastTime > roughness)
		{
			float num = (Time.time + startime) % cycletime / cycletime;
			lastTime = Time.time;
			if (Object.op_Implicit((Object)(object)mat))
			{
				mat.SetColor(colType, grad.Evaluate(num));
			}
		}
	}
}
namespace AllTameable
{
	[Serializable]
	public class TradeAmount
	{
		public string tradeItem;

		public int tradeAmt;
	}
	public class AllTame_Interactable : MonoBehaviour, Hoverable, Interactable
	{
		public Character m_character;

		public ZNetView m_nview;

		public Dictionary<string, int> tradelist = new Dictionary<string, int>();

		public string[] tradeItems = new string[20];

		public int[] tradeAmounts = new int[20];

		public void Awake()
		{
			ZNetScene instance = ZNetScene.instance;
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_character = ((Component)this).GetComponent<Character>();
			createTradeList();
		}

		public void createTradeList()
		{
			int num = tradeItems.Length;
			for (int i = 0; i < num; i++)
			{
				int value;
				try
				{
					value = tradeAmounts[i];
				}
				catch
				{
					value = 1;
				}
				if (!tradelist.ContainsKey(tradeItems[i]))
				{
					tradelist.Add(tradeItems[i], value);
				}
			}
		}

		public virtual string GetHoverText()
		{
			Tameable component = ((Component)this).GetComponent<Tameable>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return component.GetHoverText();
			}
			return "";
		}

		public virtual string GetHoverName()
		{
			Tameable component = ((Component)this).GetComponent<Tameable>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return component.GetHoverName();
			}
			return Localization.instance.Localize(m_character.m_name);
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			if (!m_nview.IsValid())
			{
				return false;
			}
			try
			{
				foreach (KeyValuePair<string, int> item2 in tradelist)
				{
					DBG.blogDebug("Allowed Trades: " + item2.Key + " with amount " + item2.Value);
				}
				DBG.blogDebug("Tradelist size=" + tradelist.Count);
				DBG.blogDebug("item.m_dropPrefab.name=" + ((Object)item.m_dropPrefab).name);
				if (!tradelist.TryGetValue(((Object)item.m_dropPrefab).name, out var value))
				{
					DBG.blogDebug(((Object)item.m_dropPrefab).name + " is not in trade list");
					return false;
				}
				Inventory inventory = user.GetInventory();
				int num = inventory.CountItems(item.m_shared.m_name, -1, true);
				if (num >= value)
				{
					DBG.blogDebug("Attempting Trade");
					if (m_character.IsTamed())
					{
						return false;
					}
					Tameable val = new Tameable();
					val = ((Component)m_character).gameObject.GetComponent<Tameable>();
					if (!((Object)(object)val != (Object)null))
					{
						DBG.blogDebug("Not tameable");
						return false;
					}
					val.Tame();
					bool flag = inventory.RemoveItem(item, value);
					DBG.blogDebug("Recruited " + m_character.m_name);
				}
				else
				{
					DBG.blogDebug("Not enough " + item.m_shared.m_name + ", need " + value);
					((Character)user).Message((MessageType)2, "Not enough " + item.m_shared.m_name + ", need " + value, 0, (Sprite)null);
				}
			}
			catch (Exception)
			{
			}
			return true;
		}
	}
	internal class CustomProcreationPatches
	{
		[HarmonyPatch(typeof(Procreation), "Procreate")]
		public static class InterceptProcreation
		{
			private static GameObject OnProcreation(GameObject child, Procreation procreation)
			{
				DBG.blogDebug("in OnProcreation");
				Character component = child.GetComponent<Character>();
				Character component2 = ((Component)procreation).gameObject.GetComponent<Character>();
				EggGrow component3 = child.GetComponent<EggGrow>();
				if (!Object.op_Implicit((Object)(object)component) && !Object.op_Implicit((Object)(object)component3))
				{
					DBG.blogWarning("Procreation, No Child");
					return child;
				}
				if (!Object.op_Implicit((Object)(object)component2))
				{
					DBG.blogWarning("No Parent, setting tame and level manually");
					if (Object.op_Implicit((Object)(object)component))
					{
						component.SetTamed(true);
						component.SetLevel(1);
					}
					if (Object.op_Implicit((Object)(object)component3))
					{
						child.GetComponent<ItemDrop>().SetQuality(0);
					}
					return child;
				}
				ProcreationInfo procreationInfo = default(ProcreationInfo);
				if (!child.gameObject.TryGetComponent<ProcreationInfo>(ref procreationInfo))
				{
					DBG.blogDebug("Adding Procinfo");
					procreationInfo = child.gameObject.AddComponent<ProcreationInfo>();
				}
				DBG.blogDebug("in onProcreate");
				DBG.blogDebug("Attempting Custom Procreation");
				procreationInfo.SetCreature(component2);
				return child;
			}

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				MethodInfo procreationHook = AccessTools.DeclaredMethod(typeof(InterceptProcreation), "OnProcreation", (Type[])null, (Type[])null);
				MethodInfo instantiator = typeof(Object).GetMethods().First((MethodInfo m) => m.Name == "Instantiate" && m.GetParameters().Length == 3 && m.GetParameters()[1].ParameterType == typeof(Vector3) && m.GetParameters()[2].ParameterType == typeof(Quaternion) && m.ContainsGenericParameters).MakeGenericMethod(typeof(GameObject));
				foreach (CodeInstruction instruction in instructions)
				{
					yield return instruction;
					if (instruction.opcode == OpCodes.Call && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)instantiator))
					{
						yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
						yield return new CodeInstruction(OpCodes.Call, (object)procreationHook);
					}
				}
				foreach (CodeInstruction instruction2 in instructions)
				{
					_ = instruction2;
				}
			}
		}

		[HarmonyPatch(typeof(EggGrow), "GrowUpdate")]
		public static class InterceptEggGrowup
		{
			private static GameObject OnEggGrowup(GameObject adult, EggGrow growup)
			{
				DBG.blogDebug("EggGrow adult=" + ((Object)adult).name);
				Character component = adult.GetComponent<Character>();
				ItemDrop component2 = ((Component)growup).GetComponent<ItemDrop>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					DBG.blogWarning("Growup, No Adult");
					return adult;
				}
				component.SetTamed(growup.m_tamed);
				component.SetLevel(component2.m_itemData.m_quality);
				DBG.blogDebug("set lvl=" + component.m_level + ", egg+1=" + (component2.m_itemData.m_quality + 1));
				DBG.blogDebug("Attempting custom Growup");
				ProcreationInfo procreationInfo = default(ProcreationInfo);
				if (!((Component)growup).gameObject.TryGetComponent<ProcreationInfo>(ref procreationInfo))
				{
					DBG.blogDebug("Adding Procinfo to Growup");
					procreationInfo = ((Component)growup).gameObject.AddComponent<ProcreationInfo>();
				}
				procreationInfo.SetGrow(component);
				return adult;
			}

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				MethodInfo growupHook = AccessTools.DeclaredMethod(typeof(InterceptEggGrowup), "OnEggGrowup", (Type[])null, (Type[])null);
				MethodInfo instantiator = typeof(Object).GetMethods().First((MethodInfo m) => m.Name == "Instantiate" && m.GetParameters().Length == 3 && m.GetParameters()[1].ParameterType == typeof(Vector3) && m.GetParameters()[2].ParameterType == typeof(Quaternion) && m.ContainsGenericParameters).MakeGenericMethod(typeof(GameObject));
				foreach (CodeInstruction instruction in instructions)
				{
					yield return instruction;
					if (instruction.opcode == OpCodes.Call && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)instantiator))
					{
						yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
						yield return new CodeInstruction(OpCodes.Call, (object)growupHook);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Growup), "GrowUpdate")]
		public static class InterceptGrowup
		{
			private static GameObject OnGrowup(GameObject adult, Growup growup)
			{
				DBG.blogDebug("adult=" + ((Object)adult).name);
				Character component = adult.GetComponent<Character>();
				Character component2 = ((Component)growup).gameObject.GetComponent<Character>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					DBG.blogWarning("Growup, No Adult");
					return adult;
				}
				if (!Object.op_Implicit((Object)(object)component2))
				{
					DBG.blogWarning("No Growup, setting tame and level manually");
					component.SetTamed(true);
					component.SetLevel(1);
					return adult;
				}
				component.SetTamed(component2.IsTamed());
				component.SetLevel(component2.GetLevel());
				DBG.blogDebug("Attempting custom Growup");
				ProcreationInfo procreationInfo = default(ProcreationInfo);
				if (!((Component)component2).gameObject.TryGetComponent<ProcreationInfo>(ref procreationInfo))
				{
					procreationInfo = ((Component)component2).gameObject.AddComponent<ProcreationInfo>();
				}
				procreationInfo.SetGrow(component);
				return adult;
			}

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
			{
				MethodInfo growupHook = AccessTools.DeclaredMethod(typeof(InterceptGrowup), "OnGrowup", (Type[])null, (Type[])null);
				MethodInfo instantiator = typeof(Object).GetMethods().First((MethodInfo m) => m.Name == "Instantiate" && m.GetParameters().Length == 3 && m.GetParameters()[1].ParameterType == typeof(Vector3) && m.GetParameters()[2].ParameterType == typeof(Quaternion) && m.ContainsGenericParameters).MakeGenericMethod(typeof(GameObject));
				foreach (CodeInstruction instruction in instructions)
				{
					yield return instruction;
					if (instruction.opcode == OpCodes.Call && CodeInstructionExtensions.OperandIs(instruction, (MemberInfo)instantiator))
					{
						yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
						yield return new CodeInstruction(OpCodes.Call, (object)growupHook);
					}
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Character), "SetLevel")]
		private static void Prefix(Character __instance, ref int level)
		{
			if (Object.op_Implicit((Object)(object)((Component)__instance).gameObject.GetComponent<ProcreationInfo>()))
			{
				level = ((Component)__instance).gameObject.GetComponent<ProcreationInfo>().GetLevel(level);
				DBG.blogDebug("level is " + level);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(ItemDrop), "SetQuality")]
		private static void Prefix(ItemDrop __instance, ref int quality)
		{
			if (Object.op_Implicit((Object)(object)((Component)__instance).gameObject.GetComponent<ProcreationInfo>()))
			{
				quality = ((Component)__instance).gameObject.GetComponent<ProcreationInfo>().GetLevel(quality);
				DBG.blogDebug("quality is " + quality);
			}
		}
	}
	public class SharedContent
	{
		[HarmonyPatch(typeof(InventoryGui), "SetupRequirementList")]
		[HarmonyPostfix]
		private static void SetupRequirementList_Patch(InventoryGui __instance, ref int quality, ref Player player, ref bool allowedQuality)
		{
			int count = __instance.m_reqList.Count;
			int num = __instance.m_recipeRequirementList.Length;
			if (count <= num)
			{
				return;
			}
			string text = "";
			int num2 = (int)Mathf.Ceil((float)__instance.m_reqList.Count / (float)num);
			int num3 = (int)(Time.fixedTime * 0.63f) % num2 * num;
			if (!allowedQuality)
			{
				return;
			}
			int num4 = num3;
			for (int i = 0; i < num; i++)
			{
				if (num4 >= __instance.m_reqList.Count)
				{
					InventoryGui.HideRequirement(__instance.m_recipeRequirementList[i].transform);
				}
				else if (InventoryGui.SetupRequirement(__instance.m_recipeRequirementList[i].transform, __instance.m_reqList[num4], player, true, quality, 1))
				{
					text = text + ((Object)__instance.m_reqList[num4].m_resItem).name + ",";
					num4++;
				}
			}
		}
	}
	public class ZDOChanger : MonoBehaviour
	{
		public string newName = null;

		private void Awake()
		{
			ZNetView component = ((Component)this).gameObject.GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid())
			{
				DBG.blogDebug(" ZDOChanger invalid ZNetView");
				return;
			}
			if (newName == null)
			{
				newName = ((Object)((Component)this).gameObject).name.Replace("_tamed", "").Replace("(Clone)", "");
				DBG.blogDebug("Replaced Name");
			}
			if (!Object.op_Implicit((Object)(object)ZNetScene.instance.GetPrefab(StringExtensionMethods.GetStableHashCode(newName))))
			{
				DBG.blogWarning("Did not find Prefab " + newName + " in ZNetView");
				return;
			}
			((Object)((Component)this).gameObject).name = newName + "(Clone)";
			component.GetZDO().SetPrefab(StringExtensionMethods.GetStableHashCode(newName));
			DBG.blogDebug("Set new ZDO Prefab");
		}
	}
	internal class SpawnedHostilePatches
	{
		private static void SetTamedAttacks(Character character)
		{
			Humanoid val = (Humanoid)(object)((character is Humanoid) ? character : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Inventory inventory = val.m_inventory;
			if (inventory == null)
			{
				return;
			}
			if (inventory.NrOfItems() > 0)
			{
				for (int num = inventory.m_inventory.Count - 1; num >= 0; num--)
				{
					if (!((Object)(object)inventory.m_inventory[num].m_dropPrefab == (Object)null) && Plugin.TamedAttackVariants.TryGetValue(((Object)inventory.m_inventory[num].m_dropPrefab).name, out var value))
					{
						inventory.RemoveItem(num);
						inventory.AddItem(value, 1);
						DBG.blogWarning("Changed to tamed attack in inv " + ((Object)value).name);
					}
				}
				return;
			}
			for (int i = 0; i < val.m_defaultItems.Length; i++)
			{
				if (Plugin.TamedAttackVariants.TryGetValue(((Object)val.m_defaultItems[i]).name, out var value2))
				{
					val.m_defaultItems[i] = value2;
					DBG.blogWarning("Changed to tamed attack as default " + ((Object)value2).name);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Character), "Awake")]
		private static void CharacterSetTamedPostfix(Character __instance)
		{
			if (__instance.m_tamed)
			{
				SetTamedAttacks(__instance);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Character), "SetTamed")]
		private static void CharacterSetTamedPostfix(Character __instance, bool tamed)
		{
			if (tamed)
			{
				SetTamedAttacks(__instance);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(CharacterDrop), "GenerateDropList")]
		private static void PrefixGenerateDropList(CharacterDrop __instance)
		{
			if (!Object.op_Implicit((Object)(object)__instance.m_character))
			{
				DBG.blogWarning("No Valid Character");
			}
			else
			{
				if (!__instance.m_character.m_tamed)
				{
					return;
				}
				foreach (Drop drop in __instance.m_drops)
				{
					if (!Object.op_Implicit((Object)(object)drop.m_prefab))
					{
						DBG.blogDebug("Drop Does not Have Prefab");
					}
					else if (Object.op_Implicit((Object)(object)drop.m_prefab.GetComponent<Tameable>()))
					{
						drop.m_prefab = Object.Instantiate<GameObject>(drop.m_prefab);
						drop.m_prefab.GetComponent<Tameable>().m_startsTamed = true;
						DBG.blogDebug("Set OnDeath Creature to Tamed");
					}
				}
			}
		}
	}
	internal static class CommandGroup
	{
		public static int commandtype = Plugin.DefaultCommandType.Value;

		public static string[] commandstrings = new string[3];

		public static string[] cyclestrings = new string[3];

		public static KeyCode commandKey = (KeyCode)103;

		public static KeyCode cycleKey = (KeyCode)104;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Character), "GetHoverText")]
		private static void GetHoverText(Character __instance, ref string __result)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.useTamingTool.Value)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)((Humanoid)localPlayer).GetCurrentWeapon().m_dropPrefab == (Object)(object)ZNetScene.instance.GetPrefab(Plugin.advtoolPrefabName) && __instance.m_tamed)
			{
				try
				{
					commandKey = (KeyCode)Enum.Parse(typeof(KeyCode), Plugin.CommandKey.Value.ToUpper());
				}
				catch
				{
					DBG.blogWarning("Command key setting " + Plugin.CommandKey.Value + " is not a valid key in this context, defaulting to G");
				}
				try
				{
					cycleKey = (KeyCode)Enum.Parse(typeof(KeyCode), Plugin.CycleKey.Value.ToUpper());
				}
				catch
				{
					DBG.blogWarning("Cycle key setting " + Plugin.CycleKey.Value + " is not a valid key in this context, defaulting to H");
				}
				if (Input.GetKeyDown(cycleKey))
				{
					changeCommand();
					((Character)localPlayer).Message((MessageType)2, cycleMessage(), 0, (Sprite)null);
				}
				if (Input.GetKeyDown(commandKey))
				{
					sendCommand(__instance, localPlayer);
				}
				if (Terminal.m_cheat && Plugin.debugout.Value && Input.GetKeyDown((KeyCode)Enum.Parse(typeof(KeyCode), "Z")))
				{
					sendGrowProcreate(__instance);
				}
				addExtraCommands(ref __result);
			}
		}

		private static void sendGrowProcreate(Character thisChar)
		{
			Procreation component = ((Component)thisChar).gameObject.GetComponent<Procreation>();
			Growup component2 = ((Component)thisChar).gameObject.GetComponent<Growup>();
			if (!Object.op_Implicit((Object)(object)component) && !Object.op_Implicit((Object)(object)component2))
			{
				DBG.blogWarning("Could not find Procreation or Growup in creature, exiting command");
			}
			else if (Object.op_Implicit((Object)(object)component))
			{
				component.m_pregnancyDuration = 3f;
				component.MakePregnant();
			}
			else
			{
				component2.m_growTime = 5f;
			}
		}

		private static void sendCommand(Character thisChar, Player plr)
		{
			//IL_0044: 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)
			Tameable val = tameablefromChar(thisChar);
			if (!Object.op_Implicit((Object)(object)val))
			{
				DBG.blogWarning("Could not find Tameable in creature, exiting command");
				return;
			}
			if (!val.m_commandable)
			{
				val.m_petEffect.Create(((Component)val).transform.position, ((Component)val).transform.rotation, (Transform)null, 1f, -1);
				((Character)plr).Message((MessageType)2, val.GetHoverName() + " $hud_tamelove", 0, (Sprite)null);
				return;
			}
			List<Character> commandList = getCommandList(val);
			string text = "";
			foreach (Character item in commandList)
			{
				text = text + ((Object)item).name + ",";
			}
			DBG.blogDebug("commandstr=" + text);
			MonsterAI component = ((Component)thisChar).gameObject.GetComponent<MonsterAI>();
			if (Object.op_Implicit((Object)(object)component))
			{
				bool tameFollow = getTameFollow(component, plr);
				int num = commandGroup(commandList, plr, tameFollow);
				((Character)plr).Message((MessageType)2, getCommandMessage(thisChar, commandList.Count - num, tameFollow), 0, (Sprite)null);
			}
		}

		private static string getCommandMessage(Character thisChar, int numCommand, bool setStay)
		{
			string hoverName = thisChar.GetHoverName();
			string text = hoverName + " and " + (numCommand - 1);
			string text2 = "Follow";
			if (setStay)
			{
				text2 = "Stay";
			}
			if (numCommand == 1)
			{
				return hoverName + " was asked to " + text2;
			}
			return commandtype switch
			{
				0 => text + " others have been asked to " + text2, 
				1 => text + " mates have been asked to " + text2, 
				_ => text + " tames have been asked to " + text2, 
			};
		}

		private static string commandTypetoStr()
		{
			if ((commandstrings[0] ?? "") == "")
			{
				DBG.blogDebug("command strings made");
				commandstrings[0] = "(<color=yellow><b>Same</b></color>) ";
				commandstrings[1] = "(<color=#5CEB59><b>Mates</b></color>) ";
				commandstrings[2] = "(<color=#2b82ed><b>Any</b></color>) ";
			}
			return commandstrings[commandtype];
		}

		private static string cycleMessage()
		{
			if ((cyclestrings[0] ?? "") == "")
			{
				DBG.blogDebug("cycle strings made");
				cyclestrings[0] = "Shout at only this type of creature";
				cyclestrings[1] = "Shout at this creature and any that it can breed with";
				cyclestrings[2] = "Shout for any tamed creature in range";
			}
			return cyclestrings[commandtype];
		}

		private static void addExtraCommands(ref string result)
		{
			string text = Localization.instance.Localize("$hud_pet");
			result = result.Replace(text, text + " [<color=orange><b>" + ((object)(KeyCode)(ref cycleKey)).ToString() + "</b></color>] Cycle Shout " + commandTypetoStr());
			text = Localization.instance.Localize("$hud_rename");
			result = result.Replace(text, text + " [<color=orange><b>" + ((object)(KeyCode)(ref commandKey)).ToString() + "</b></color>] Shout");
		}

		private static int commandGroup(List<Character> chars, Player plr, bool setStay)
		{
			int num = 0;
			Tameable thisTame = default(Tameable);
			MonsterAI val = default(MonsterAI);
			foreach (Character @char in chars)
			{
				if (!((Component)@char).gameObject.TryGetComponent<Tameable>(ref thisTame))
				{
					DBG.blogDebug("No Tameable in " + ((Object)@char).name);
					num++;
					continue;
				}
				if (!((Component)@char).gameObject.TryGetComponent<MonsterAI>(ref val))
				{
					DBG.blogDebug("No MonsterAI in " + ((Object)@char).name);
					num++;
					continue;
				}
				GameObject followTarget = val.GetFollowTarget();
				if (setStay & !Object.op_Implicit((Object)(object)followTarget))
				{
					DBG.blogDebug("Leaving as Stay for " + ((Object)@char).name);
					continue;
				}
				if (!setStay)
				{
					val.SetFollowTarget((GameObject)null);
				}
				DBG.blogDebug("Sending Command to " + ((Object)@char).name);
				if (!commandSingle(thisTame, plr))
				{
					num++;
				}
			}
			return num;
		}

		private static bool commandSingle(Tameable thisTame, Player plr)
		{
			//IL_0023: 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)
			thisTame.m_lastPetTime = Time.time;
			if (thisTame.m_commandable)
			{
				thisTame.m_petEffect.Create(((Component)thisTame).transform.position, ((Component)thisTame).transform.rotation, (Transform)null, 1f, -1);
				thisTame.Command((Humanoid)(object)plr, true);
				return true;
			}
			return false;
		}

		private static Tameable tameablefromChar(Character thisChar)
		{
			Tameable component = ((Component)thisChar).gameObject.GetComponent<Tameable>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				DBG.blogDebug("No Tameable Found");
			}
			return component;
		}

		private static bool getTameFollow(MonsterAI thisMAI, Player plr)
		{
			return (Object)(object)thisMAI.m_follow == (Object)(object)((Component)plr).gameObject;
		}

		private static List<Character> getCommandList(Tameable thisTame)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			List<Character> list = new List<Character>();
			List<Character> list2 = new List<Character>();
			Character.GetCharactersInRange(((Component)thisTame).transform.position, (float)Plugin.CommandRange.Value, list);
			if (commandtype == 2)
			{
				foreach (Character item in list)
				{
					if (item.m_tamed)
					{
						list2.Add(item);
					}
				}
				return list2;
			}
			List<string> list3 = possibleMatePrefabs(thisTame);
			foreach (Character item2 in list)
			{
				if (item2.m_tamed && list3.Contains(removeClone(((Object)item2).name)))
				{
					list2.Add(item2);
				}
			}
			return list2;
		}

		public static void changeCommand()
		{
			commandtype = (commandtype + 1) % 3;
			Plugin.DefaultCommandType.Value = commandtype;
		}

		private static List<string> possibleMatePrefabs(Tameable thisTame)
		{
			List<string> list = new List<string>();
			DBG.blogDebug("thistame.name=" + ((Object)thisTame).name);
			list.Add(removeClone(((Object)thisTame).name));
			if (commandtype > 0 && Plugin.CompatMatesList.TryGetValue(removeClone(((Object)thisTame).name), out var value))
			{
				list.AddRange(value);
			}
			DBG.blogDebug("possibleMateprefabs=" + string.Join(",", list));
			return list;
		}

		public static string removeClone(string withClone)
		{
			return withClone.Replace("(Clone)", "");
		}
	}
	public class Enchants : MonoBehaviour
	{
		[Serializable]
		public class EnchantTable : ICloneable
		{
			public int EnchantType { get; set; } = 0;


			public int lvl { get; set; } = 1;


			public object Clone()
			{
				return MemberwiseClone();
			}
		}

		public enum EnchantType
		{
			None,
			Vision,
			Calming,
			Tamer,
			Aphrodisiac,
			Leader,
			BeastLord
		}

		public const float maxCalmDistance = 25f;

		public const float minCalmUpdateTime = 6f;

		public static bool effectloaded = false;

		public static GameObject vfx_Calm;

		public static GameObject vfx_noCalm;

		public const int CharacterLayer = 9;

		public const int CharacterNetLayer = 26;

		public static Collider[] charactersinarea = (Collider[])(object)new Collider[100];

		public static int mask33 = LayerMask.GetMask(new string[2] { "character", "character_net" });

		public static Dictionary<string, EnchantTable> EnchantedItemList = new Dictionary<string, EnchantTable>();

		public static GameObject Root;

		public static PrefabManager prefabmanager;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "Awake")]
		private static void PostfixPlayerAwake(Player __instance)
		{
			if (!((Character)__instance).m_nview.IsValid())
			{
				return;
			}
			ZNetView nview = ((Character)__instance).m_nview;
			List<StatusEffect> statusEffects = ((Character)__instance).m_seman.m_statusEffects;
			string[] array = new string[3] { "SE_SpeedTame", "SE_Calming", "SE_BestialCommand" };
			for (int i = 0; i < array.Length; i++)
			{
				bool flag = false;
				foreach (StatusEffect item in statusEffects)
				{
					if (((Object)item).name == array[i])
					{
						flag = true;
					}
				}
				if (!flag)
				{
					DBG.blogDebug("setting " + array[i] + " to 0");
					nview.GetZDO().Set(array[i], 0);
				}
			}
			nview.GetZDO().Set("AT_plrUpdate", 0);
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(BaseAI), "CanHearTarget", new Type[]
		{
			typeof(Transform),
			typeof(float),
			typeof(Character)
		})]
		private static void PrefixCanHearTarget(BaseAI __instance, Transform me, ref float hearRange, Character target)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			float num = Vector3.Distance(me.position, ((Component)target).transform.position);
			if (!(num > 25f))
			{
				hearRange *= CalmModifier(me, target);
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(BaseAI), "CanSeeTarget", new Type[]
		{
			typeof(Transform),
			typeof(Vector3),
			typeof(float),
			typeof(float),
			typeof(bool),
			typeof(bool),
			typeof(Character)
		})]
		private static void PrefixCanSeeTarget(BaseAI __instance, Transform me, ref float viewRange, ref float viewAngle, Character target)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)target == (Object)null) && !((Object)(object)me == (Object)null))
			{
				float num = Vector3.Distance(me.position, ((Component)target).transform.position);
				if (!(num > 25f))
				{
					float num2 = CalmModifier(me, target);
					viewRange *= num2;
					viewAngle *= num2;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "FixedUpdate")]
		private static void PostfixPlayerFixedUpdate(Player __instance)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || (double)(Time.time - ((Character)__instance).m_nview.GetZDO().GetFloat("AT_plrUpdate", 0f)) < 0.75)
			{
				return;
			}
			((Character)__instance).m_nview.GetZDO().Set("AT_plrUpdate", Time.time);
			int num = Physics.OverlapSphereNonAlloc(((Component)__instance).transform.localPosition, 50f, charactersinarea, mask33);
			bool flag = Math.Round(Time.time % 5f) == 0.0;
			Character val = default(Character);
			for (int i = 0; i < num; i++)
			{
				if (!((Object)(object)charactersinarea[i] == (Object)null) && (((Component)charactersinarea[i]).gameObject.layer == 9 || ((Component)charactersinarea[i]).gameObject.layer == 26) && ((Component)charactersinarea[i]).gameObject.TryGetComponent<Character>(ref val) && !(((object)val).GetType() == typeof(Player)) && val.m_nview.IsValid() && !val.m_nview.IsOwner())
				{
					GetSetCalm(((Component)val).transform, val.m_nview);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(MonsterAI), "UpdateAI")]
		private static void PostfixBaseAIUpdateAI(MonsterAI __instance)
		{
			LongUpdateAI(__instance);
		}

		public static void LongUpdateAI(MonsterAI mAI)
		{
			if (((BaseAI)mAI).m_nview.IsValid() && ((BaseAI)mAI).m_nview.IsOwner() && ((BaseAI)mAI).m_character.IsTamed())
			{
				float num = Time.time - ((BaseAI)mAI).m_nview.GetZDO().GetFloat("AT_LongUpdate", 0f);
				num = ((num > 0f) ? num : (0f - num));
				if (!(num < 5f))
				{
					((BaseAI)mAI).m_nview.GetZDO().Set("AT_LongUpdate", Time.time);
					receivePlrEffects(mAI, 15f);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Attack), "ModifyDamage")]
		private static void PostfixAttackModifyDamage(Attack __instance, ref HitData hitData)
		{
			if (Object.op_Implicit((Object)(object)__instance.m_character))
			{
				ZNetView nview = ((Character)__instance.m_character).m_nview;
				if (nview.IsValid() && nview.IsOwner() && nview.GetZDO().GetFloat("SE_hasBC", 0f) > Time.time)
				{
					((DamageTypes)(ref hitData.m_damage)).Modify(1.3f);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Tameable), "DecreaseRemainingTime")]
		private static void PrefixDecreaseRemainingTime(Tameable __instance, ref float time)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			time += getPlayersSpeedTame(((Component)__instance).transform.position, 20f);
		}

		public static float CalmModifier(Transform me, Character target)
		{
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Expected O, but got Unknown
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f;
			float num2 = 0f;
			float num3 = 0f;
			Tameable component = ((Component)me).gameObject.GetComponent<Tameable>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return 1f;
			}
			if (component.m_character.IsTamed())
			{
				return 1f;
			}
			ZNetView nview = component.m_nview;
			bool flag = nview.IsValid();
			ZDO val = null;
			float time = Time.time;
			if (flag)
			{
				val = nview.GetZDO();
				num2 = val.GetFloat("AT_CalmUpdate", 0f);
				num3 = val.GetFloat("AT_LastCalmUpdate", 0f);
				if (num3 > time)
				{
					num3 = -50f;
				}
				num = 1f - val.GetFloat("AT_CalmModifier", 0f);
				if (num2 > 300f * (1f - num))
				{
					if (((Component)me).gameObject.GetComponent<BaseAI>().IsAlerted())
					{
						num2 = Math.Min(300f * (1f - num) + 2f, num2);
					}
					val.Set("AT_CalmUpdate", num2 - (time - num3));
					val.Set("AT_LastCalmUpdate", time);
					return num;
				}
			}
			bool flag2 = ((Component)me).gameObject.GetComponent<BaseAI>().IsAlerted();
			float num4 = 6f;
			if (target.IsPlayer())
			{
				Player plr = (Player)target;
				int num5 = Math.Min(GetMagicLvlFromZDO(plr, EnchantType.Calming), 95);
				num5 = (int)Math.Max(-6f + (1f - num) * 100f, num5);
				num = 1f;
				if (num5 > 0 && Vector3.Distance(me.position, ((Component)target).transform.position) < (float)num5)
				{
					num = (100f - (float)num5) / 100f;
					num4 = (float)num5 * 4f;
					DBG.blogDebug(((Object)component).name.Replace("(Clone)", "") + ":calm of " + num + " set for " + num4);
					if (!flag2)
					{
						val.Set("AT_isCalm", true);
						if (Object.op_Implicit((Object)(object)GetCalmEffect()))
						{
							GameObject val2 = Object.Instantiate<GameObject>(vfx_Calm, me);
							TimedDestruction orAddComponent = ExposedGameObjectExtension.GetOrAddComponent<TimedDestruction>(val2);
							orAddComponent.m_timeout = num5;
							orAddComponent.Trigger();
						}
						else
						{
							DBG.blogDebug("did not find calm prefab");
						}
					}
				}
			}
			if (flag2 || num >= 1f)
			{
				val.Set("AT_isCalm", false);
				Transform val3 = me.Find("vfx_Calm(Clone)");
				if (Object.op_Implicit((Object)(object)val3))
				{
					DBG.blogDebug("removing calm prefab when alerted");
					val3.parent = null;
					Object.Destroy((Object)(object)((Component)val3).gameObject);
					if (!Object.op_Implicit((Object)(object)me.Find("vfx_noCalm(Clone)")) && Object.op_Implicit((Object)(object)GetnoCalmEffect()))
					{
						GameObject val4 = Object.Instantiate<GameObject>(vfx_noCalm, me);
					}
				}
			}
			if (flag)
			{
				val.Set("AT_CalmUpdate", num4 - (time - num3));
				val.Set("AT_CalmModifier", 1f - num);
				val.Set("AT_LastCalmUpdate", time);
			}
			return num;
		}

		public static void GetSetCalm(Transform effectParent, ZNetView m_nview)
		{
			ZDO zDO = m_nview.GetZDO();
			Transform val = effectParent.Find("vfx_Calm(Clone)");
			if (zDO.GetBool("AT_isCalm", false))
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					if (Object.op_Implicit((Object)(object)GetCalmEffect()))
					{
						DBG.blogDebug("adding calm");
						Object.Instantiate<GameObject>(vfx_Calm, effectParent);
					}
					else
					{
						DBG.blogDebug("Could not get Calm Effect");
					}
				}
			}
			else if (Object.op_Implicit((Object)(object)val))
			{
				if (Object.op_Implicit((Object)(object)GetnoCalmEffect()))
				{
					DBG.blogDebug("removing calm");
					Object.Instantiate<GameObject>(vfx_noCalm, effectParent);
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
				else
				{
					DBG.blogDebug("Could not get noCalm Effect");
				}
			}
		}

		public static GameObject GetCalmEffect()
		{
			if (!Object.op_Implicit((Object)(object)vfx_Calm))
			{
				DBG.blogDebug("Resetting Calm Effect");
				vfx_Calm = PrefabManager.Instance.GetPrefab("vfx_Calm");
			}
			return vfx_Calm;
		}

		public static GameObject GetnoCalmEffect()
		{
			if (!Object.op_Implicit((Object)(object)vfx_noCalm))
			{
				DBG.blogDebug("Resetting noCalm Effect");
				vfx_noCalm = PrefabManager.Instance.GetPrefab("vfx_noCalm");
			}
			return vfx_noCalm;
		}

		public static List<ItemData> getEquipped(Player plr)
		{
			List<ItemData> list = new List<ItemData>();
			AddEquipped(ref list, ((Humanoid)plr).m_utilityItem);
			AddEquipped(ref list, ((Humanoid)plr).m_helmetItem);
			AddEquipped(ref list, ((Humanoid)plr).m_legItem);
			AddEquipped(ref list, ((Humanoid)plr).m_rightItem);
			AddEquipped(ref list, ((Humanoid)plr).m_leftItem);
			AddEquipped(ref list, ((Humanoid)plr).m_chestItem);
			AddEquipped(ref list, ((Humanoid)plr).m_shoulderItem);
			return list;
		}

		public static List<ItemData> getHolding(Player plr)
		{
			List<ItemData> list = new List<ItemData>();
			AddEquipped(ref list, ((Humanoid)plr).m_rightItem);
			AddEquipped(ref list, ((Humanoid)plr).m_leftItem);
			return list;
		}

		public static void AddEquipped(ref List<ItemData> list, ItemData item)
		{
			if (item != null)
			{
				list.Add(item);
			}
		}

		public static int GetMagicLvlFromZDO(Player plr, EnchantType enchantType)
		{
			ZNetView nview = ((Character)plr).m_nview;
			if (!nview.IsValid())
			{
				return 0;
			}
			if (enchantType == EnchantType.Calming && nview.GetZDO().GetFloat("SE_Calming", 0f) > Time.time)
			{
				return 40;
			}
			return 0;
		}

		public static float getPlayersSpeedTame(Vector3 center, float maxdist)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			List<Player> s_players = Player.s_players;
			float num = 0f;
			float time = Time.time;
			foreach (Player item in s_players)
			{
				if (((Character)item).m_nview.IsValid() && !(Vector3.Distance(((Component)item).transform.position, center) > maxdist))
				{
					ZDO zDO = ((Character)item).m_nview.GetZDO();
					if (time < zDO.GetFloat("SE_SpeedTame", 0f))
					{
						num += 3f;
					}
					if (time < zDO.GetFloat("SE_BestialCommand", 0f))
					{
						num += 1f;
					}
				}
			}
			return num;
		}

		public static void receivePlrEffects(MonsterAI mAI, float maxdist)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			List<Player> s_players = Player.s_players;
			Vector3 position = ((Component)mAI).transform.position;
			foreach (Player item in s_players)
			{
				if (!((Character)item).m_nview.IsValid() || Vector3.Distance(((Component)item).transform.position, position) > maxdist || !(((Character)item).m_nview.GetZDO().GetFloat("SE_BestialCommand", 0f) > Time.time))
				{
					continue;
				}
				((BaseAI)mAI).m_nview.GetZDO().Set("SE_hasBC", Time.time + 15f);
				break;
			}
		}

		public void Clear()
		{
		}

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			Root = new GameObject("ATEnchants");
			Root.transform.SetParent(Plugin.Root.transform);
			Root.SetActive(false);
			prefabmanager = Plugin.prefabManager;
			vfx_Calm = PrefabManager.Instance.GetPrefab("vfx_Calm");
			vfx_noCalm = PrefabManager.Instance.GetPrefab("vfx_noCalm");
		}
	}
	public class ProcreationInfo : MonoBehaviour
	{
		public enum Effect_CLLC
		{
			None,
			Aggressive,
			Quick,
			Regenerating,
			Curious,
			Splitting,
			Armored
		}

		public enum Infusion_CLLC
		{
			None,
			Lightning,
			Fire,
			Frost,
			Poison,
			Chaos,
			Spirit
		}

		public int dad_lvl = 1;

		public string dad_MonMod = "";

		public long DNA_offspring = 0L;

		private int level = 1;

		private bool newLevel = false;

		public Effect_CLLC dad_effect { get; set; } = Effect_CLLC.None;


		public Infusion_CLLC dad_infusion { get; set; } = Infusion_CLLC.None;


		public ProcreationInfo mom_info { get; set; } = null;


		public int GetLevel(int oldLevel)
		{
			if (newLevel)
			{
				return level;
			}
			return oldLevel;
		}

		private void Awake()
		{
			if (!Object.op_Implicit((Object)(object)((Component)this).GetComponentInParent<Growup>()) & !Object.op_Implicit((Object)(object)((Component)this).GetComponentInParent<EggGrow>()))
			{
				Character component = ((Component)this).gameObject.GetComponent<Character>();
				if (Object.op_Implicit((Object)(object)component))
				{
					ParentStart();
				}
				else
				{
					DBG.blogDebug("no character");
				}
			}
			if (!Object.op_Implicit((Object)(object)((Component)this).GetComponentInParent<EggGrow>()))
			{
				return;
			}
			ItemDrop component2 = ((Component)this).gameObject.GetComponent<ItemDrop>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				ItemData itemData = component2.m_itemData;
				if (!itemData.m_customData.TryGetValue("Infusion", out var value))
				{
					value = "None";
				}
				if (!itemData.m_customData.TryGetValue("ExtraEffect", out var value2))
				{
					value2 = "None";
				}
				if (value != "None" || value2 != "None")
				{
					itemData.m_shared.m_maxStackSize = 1;
				}
				int quality = GetLevel(component2.m_itemData.m_quality);
				DBG.blogDebug("Setting Quality to " + quality);
				component2.SetQuality(quality);
			}
		}

		public void SetGrow(Character adultchar)
		{
			DBG.blogDebug("inSetGrow");
			Character component = ((Component)this).gameObject.GetComponent<Character>();
			bool flag = (Object)(object)component == (Object)null;
			ItemDrop component2 = ((Component)this).gameObject.GetComponent<ItemDrop>();
			string text = (flag ? iDropGetDNA(component2) : "");
			if (Plugin.UseCLLC)
			{
				Effect_CLLC infusion;
				Infusion_CLLC infusion2;
				if (flag)
				{
					DBG.blogDebug("No Char");
					infusion = iDropGetEff(component2);
					infusion2 = iDropGetInf(component2);
				}
				else
				{
					DBG.blogDebug("Has Char");
					infusion2 = AllTameable.CLLC.CLLC.GetInfusionCreature(component);
					infusion = AllTameable.CLLC.CLLC.GetExtraEffectCreature(component);
				}
				AllTameable.CLLC.CLLC.SetInfusionCreature(adultchar, infusion2);
				AllTameable.CLLC.CLLC.SetExtraEffectCreature(adultchar, infusion);
			}
			if (Plugin.useDNA)
			{
				DBG.blogDebug("in useDNA");
				AllTameable.DNA.DNA dNA = default(AllTameable.DNA.DNA);
				if (!((Component)this).gameObject.TryGetComponent<AllTameable.DNA.DNA>(ref dNA))
				{
					DBG.blogDebug("Adding child DNA");
					dNA = ((Component)this).gameObject.AddComponent<AllTameable.DNA.DNA>();
				}
				AllTameable.DNA.DNA dNA2 = default(AllTameable.DNA.DNA);
				if (!((Component)adultchar).gameObject.TryGetComponent<AllTameable.DNA.DNA>(ref dNA2))
				{
					DBG.blogDebug("Adding adult DNA");
					dNA2 = ((Component)adultchar).gameObject.AddComponent<AllTameable.DNA.DNA>();
				}
				if (text != "")
				{
					dNA2.DNA_hash = long.Parse(text);
					DBG.blogDebug("Setting DNA from iDrop");
				}
				else
				{
					dNA2.DNA_hash = dNA.DNA_hash;
				}
				DBG.blogDebug("Attempting Adult DNA Sync");
				dNA2.restoreColor();
				dNA2.ParseMSG();
				dNA2.setAttributes();
			}
			if (Plugin.useMonMod)
			{
				string monMod;
				if (flag)
				{
					DBG.blogDebug("No Char");
					monMod = iDropGetMonMod(component2);
				}
				else
				{
					monMod = MonsterModifiers_AT.getModifiers(component);
				}
				MonsterModifiers_AT.SetModifiers(adultchar, monMod);
			}
		}

		public int inheritValue(int mom_val, int dad_val)
		{
			if (mom_val != 0 || dad_val != 0)
			{
				int num = Random.Range(0, 100);
				if (num > 60)
				{
					DBG.blogDebug("IsDadVal");
					return dad_val;
				}
				if (num > 20)
				{
					DBG.blogDebug("IsMomVal");
					return mom_val;
				}
				DBG.blogDebug("IsNoVal");
			}
			return 0;
		}

		public static string iDropGetDNA(ItemDrop iDrop)
		{
			string result = "";
			if (Object.op_Implicit((Object)(object)iDrop) && Plugin.useDNA && iDrop.m_itemData.m_customData.TryGetValue("AT_DNA", out var value))
			{
				result = value;
				DBG.blogDebug("got DNA from iDrop");
			}
			return result;
		}

		public static string iDropGetMonMod(ItemDrop iDrop)
		{
			string result = "";
			if (Object.op_Implicit((Object)(object)iDrop) && Plugin.useMonMod && iDrop.m_itemData.m_customData.TryGetValue("AT_MonMod", out var value))
			{
				result = value;
				DBG.blogDebug("got MonMod from iDrop");
			}
			return result;
		}

		public void SetCreature(Character mother)
		{
			try
			{
				ProcreationInfo procreationInfo = default(ProcreationInfo);
				if (!((Component)mother).gameObject.TryGetComponent<ProcreationInfo>(ref procreationInfo))
				{
					DBG.blogDebug("Adding Procinfo to mother");
					procreationInfo = ((Component)mother).gameObject.AddComponent<ProcreationInfo>();
				}
				else
				{
					procreationInfo.ParentStart();
				}
				mom_info = procreationInfo;
				int num = mother.GetLevel();
				dad_lvl = mom_info.dad_lvl;
				DBG.blogDebug("dad_lvl =" + dad_lvl);
				level = num;
				if (Plugin.AllowMutation.Value && Random.Range(0, 100) < Plugin.MutationChanceLvl.Value)
				{
					DBG.blogDebug("Has Mutation in Level");
					int num2 = Mathf.Max(Mathf.Min(num, dad_lvl) - 1, 1);
					int num3 = Mathf.Max(num, dad_lvl) + 1;
					int num4 = Mathf.Min(100, Random.Range(0, 100) + 10);
					level = num2 + Mathf.RoundToInt((float)(num4 * (num3 - num2)) / 100f);
					if (Plugin.MaxMutationLvl.Value > 0 && level > Plugin.MaxMutationLvl.Value)
					{
						level = Plugin.MaxMutationLvl.Value;
					}
				}
				else if (Random.Range(0, 100) > 50)
				{
					level = dad_lvl;
				}
				newLevel = true;
				Character component = ((Component)this).gameObject.GetComponent<Character>();
				bool flag = Object.op_Implicit((Object)(object)((Component)this).gameObject.GetComponent<EggGrow>());
				DBG.blogDebug("isEgg=" + flag);
				if ((Object)(object)component != (Object)null)
				{
					component.SetLevel(level);
					component.SetTamed(true);
				}
				ItemDrop val = null;
				if (flag)
				{
					val = ((Component)this).gameObject.GetComponent<ItemDrop>();
					val.SetQuality(level - 1);
					DBG.blogDebug("setting egg quality to =" + (level - 2));
				}
				try
				{
					if (Plugin.useMonMod)
					{
						string modifiers = MonsterModifiers_AT.getModifiers(mother);
						string text = MonsterModifiers_AT.CreateChildModifiers(modifiers, mom_info.dad_MonMod, level);
						if (flag)
						{
							Utils2.addOrUpdateCustomData(val.m_itemData.m_customData, "AT_MonMod", text);
							if (text.Length > 0)
							{
								DBG.blogDebug("Set stack size 1");
								val.m_itemData.m_shared.m_maxStackSize = 1;
								val.Save();
							}
						}
						else
						{
							MonsterModifiers_AT.SetModifiers(component, text);
						}
					}
				}
				catch
				{
					DBG.blogWarning("Failed MonsterModifiers Compat");
				}
				try
				{
					if (Plugin.UseCLLC)
					{
						dad_infusion = mom_info.dad_infusion;
						dad_effect = mom_info.dad_effect;
						SetInfusionExtraEffect(mother, flag);
					}
				}
				catch
				{
					DBG.blogWarning("Failed CLLC Compat");
				}
				try
				{
					if (Plugin.useDNA)
					{
						DBG.blogDebug("in useDNA offspring");
						AllTameable.DNA.DNA dNA = default(AllTameable.DNA.DNA);
						if (!((Component)this).gameObject.TryGetComponent<AllTameable.DNA.DNA>(ref dNA))
						{
							DBG.blogDebug("Adding DNA");
							AllTameable.DNA.DNA dNA2 = new AllTameable.DNA.DNA();
							dNA2.DNA_hash = procreationInfo.DNA_offspring;
							dNA = ((Component)this).gameObject.AddComponent<AllTameable.DNA.DNA>(dNA2);
						}
						dNA.restoreColor();
						dNA.DNA_hash = procreationInfo.DNA_offspring;
						dNA.ParseMSG();
						dNA.isWild = false;
						dNA.setAttributes();
						dNA.SetZDO();
						DBG.blogDebug("child/parent = " + (dNA.DNA_hash - procreationInfo.DNA_offspring));
						if (flag)
						{
							Utils2.addOrUpdateCustomData(val.m_itemData.m_customData, "AT_DNA", dNA.DNA_hash.ToString());
						}
					}
				}
				catch
				{
					DBG.blogWarning("Failed DNA Compat");
				}
				if (flag)
				{
					setStackSize(val.m_itemData);
					DBG.blogWarning("Set Creature max stack size=" + val.m_itemData.m_shared.m_maxStackSize);
				}
			}
			catch
			{
				try
				{
					DBG.blogDebug("Major failure of procreation");
					level = mother.GetLevel();
				}
				catch
				{
					DBG.blogDebug("Catastrophic failure of procreation");
					level = 0;
				}
			}
		}

		private void SetInfo(Character other)
		{
			dad_lvl = other.GetLevel();
			if (Plugin.UseCLLC)
			{
				try
				{
					dad_effect = AllTameable.CLLC.CLLC.GetExtraEffectCreature(other);
				}
				catch
				{
					DBG.blogWarning("Error when trying to get Effect of Father");
				}
				try
				{
					dad_infusion = AllTameable.CLLC.CLLC.GetInfusionCreature(other);
				}
				catch
				{
					DBG.blogWarning("Error when trying to get Infusion of Father");
				}
			}
			if (Plugin.useMonMod)
			{
				try
				{
					dad_MonMod = MonsterModifiers_AT.getModifiers(other);
				}
				catch
				{
					DBG.blogWarning("Error when trying to get Monster Modifier of Father");
				}
			}
		}

		public void ParentStart()
		{
			//IL_0198: 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_0112: 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)
			Character val = null;
			float num = 999999f;
			BaseAI componentInParent = ((Component)this).GetComponentInParent<BaseAI>();
			List<Character> allCharacters = Character.GetAllCharacters();
			if (!Plugin.CompatMatesList.TryGetValue(Utils.GetPrefabName(((Component)componentInParent).gameObject), out var value))
			{
				value = new List<string> { Utils.GetPrefabName(((Component)componentInParent).gameObject) };
			}
			List<string> list = new List<string>();
			ZNetScene instance = ZNetScene.instance;
			list.Add(((Object)((Component)componentInParent).gameObject).name);
			foreach (string item in value)
			{
				list.Add(item + "(Clone)");
			}
			foreach (Character item2 in allCharacters)
			{
				if (!((Object)(object)((Component)item2).gameObject == (Object)(object)((Component)componentInParent).gameObject) && list.Contains(((Object)((Component)item2).gameObject).name) && ((Component)item2).GetComponent<ZNetView>().IsValid())
				{
					float num2 = Vector3.Distance(((Component)item2).transform.position, ((Component)this).transform.position);
					if (num2 < num)
					{
						val = item2;
						num = num2;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				DBG.blogDebug("Partner with name go:" + ((Object)((Component)val).gameObject).name + " is " + Vector3.Distance(((Component)val).transform.position, ((Component)this).transform.position) + "m away");
				try
				{
					SetInfo(((Component)val).GetComponent<Character>());
				}
				catch
				{
					DBG.blogWarning("Error when trying to get Level of Father, Using Mothers");
				}
				if (Plugin.useDNA)
				{
					AllTameable.DNA.DNA dNA = default(AllTameable.DNA.DNA);
					if (((Component)this).gameObject.TryGetComponent<AllTameable.DNA.DNA>(ref dNA))
					{
						DNA_offspring = dNA.getDNAOffspring(val);
					}
					else
					{
						DBG.blogDebug("Did not find DNA in creature");
					}
				}
			}
			else
			{
				dad_lvl = ((Component)this).gameObject.GetComponent<Character>().GetLevel();
			}
		}

		public static void setStackSize(ItemData iData)
		{
			bool flag = false;
			if (Plugin.UseCLLC)
			{
				if (!iData.m_customData.TryGetValue("Infusion", out var value))
				{
					value = "None";
				}
				if (!iData.m_customData.TryGetValue("ExtraEffect", out var value2))
				{
					value2 = "None";
				}
				if (value != "None" || value2 != "None")
				{
					flag = true;
				}
			}
			if (Plugin.useMonMod && iData.m_customData.TryGetValue("AT_MonMod", out var value3) && value3 != "")
			{
				flag = true;
			}
			if (flag)
			{
				iData.m_shared.m_maxStackSize = iData.m_stack;
			}
			else
			{
				iData.m_shared.m_maxStackSize = Math.Max(iData.m_stack, 20);
			}
		}

		private Effect_CLLC TryGetExtraEffect(Character thisChar)
		{
			if (Object.op_Implicit((Object)(object)thisChar.m_nview))
			{
				return AllTameable.CLLC.CLLC.GetExtraEffectCreature(thisChar);
			}
			string value = ((Component)thisChar).gameObject.GetComponent<ItemDrop>().m_itemData.m_customData["ExtraEffect"];
			if (!Enum.TryParse<Effect_CLLC>(value, out var result))
			{
				result = Effect_CLLC.None;
			}
			return result;
		}

		private Infusion_CLLC TryGetInfusion(Character thisChar)
		{
			if (Object.op_Implicit((Object)(object)thisChar.m_nview))
			{
				return AllTameable.CLLC.CLLC.GetInfusionCreature(thisChar);
			}
			string value = ((Component)thisChar).gameObject.GetComponent<ItemDrop>().m_itemData.m_customData["Infusion"];
			if (!Enum.TryParse<Infusion_CLLC>(value, out var result))
			{
				result = Infusion_CLLC.None;
			}
			return result;
		}

		public void SetInfusionExtraEffect(Character mother, bool isEgg)
		{
			DBG.blogDebug("in SetInfusionExtraEffect");
			DBG.blogDebug("In infusion effect combine");
			bool flag = false;
			bool flag2 = false;
			if (AllTameable.CLLC.CLLC.IsExtraEffectEnabled())
			{
				flag2 = true;
			}
			else
			{
				DBG.blogDebug("NoExtraEffectEnabled");
			}
			if (AllTameable.CLLC.CLLC.IsInfusionEnabled())
			{
				flag = true;
			}
			else
			{
				DBG.blogDebug("NoinfusionEnabled");
			}
			if (!flag && !flag2)
			{
				DBG.blogDebug("SkippingCLLC");
				return;
			}
			Effect_CLLC extraEffectCreature = AllTameable.CLLC.CLLC.GetExtraEffectCreature(mother);
			Infusion_CLLC infusionCreature = AllTameable.CLLC.CLLC.GetInfusionCreature(mother);
			int num = mother.GetLevel();
			dad_lvl = mom_info.dad_lvl;
			dad_effect = mom_info.dad_effect;
			dad_infusion = mom_info.dad_infusion;
			Character component;
			if (isEgg)
			{
				DBG.blogDebug("Set Infusion/Effect of Egg");
				GameObject val = Object.Instantiate<GameObject>(((Component)this).gameObject.GetComponent<EggGrow>().m_grownPrefab, PetManager.Root.transform);
				component = val.GetComponent<Character>();
				DBG.blogDebug("Clone Char of Egg=" + Object.op_Implicit((Object)(object)component));
				ZNetView component2 = ((Component)component).GetComponent<ZNetView>();
				if (!component2.IsValid() || !component2.IsOwner())
				{
					((Component)component).gameObject.AddComponent<ItemDrop>();
				}
			}
			else
			{
				component = ((Component)this).gameObject.GetComponent<Character>();
			}
			component.m_level = Mathf.RoundToInt((float)((num + dad_lvl) / 2));
			Effect_CLLC effect_CLLC = Effect_CLLC.None;
			Infusion_CLLC infusion_CLLC = Infusion_CLLC.None;
			int num2 = -1;
			int num3 = -1;
			if (Plugin.AllowMutation.Value)
			{
				if (flag2 && Random.Range(0, 100) < Plugin.MutationChanceEff.Value)
				{
					num3 = 0;
				}
				if (flag && Random.Range(0, 100) < Plugin.MutationChanceInf.Value)
				{
					num2 = 0;
				}
				for (int i = 0; i < 25; i++)
				{
					if (num3 != 0 && num2 != 0)
					{
						break;
					}
					DBG.blogDebug("i=" + i);
					if (num3 == 0)
					{
						AllTameable.CLLC.CLLC.SetExtraEffectCreature(component);
						Effect_CLLC effect_CLLC2 = TryGetExtraEffect(component);
						if (effect_CLLC2 != extraEffectCreature && effect_CLLC2 != dad_effect && effect_CLLC2 != 0)
						{
							DBG.blogDebug("Effect(" + i + ")=" + effect_CLLC2);
							DBG.blogDebug("Has Mutation in Effect");
							effect_CLLC = effect_CLLC2;
							num3 = 1;
						}
					}
					if (num2 == 0)
					{
						AllTameable.CLLC.CLLC.SetInfusionCreature(component);
						Infusion_CLLC infusion_CLLC2 = TryGetInfusion(component);
						if (infusion_CLLC2 != infusionCreature && infusion_CLLC2 != dad_infusion && infusion_CLLC2 != 0)
						{
							DBG.blogDebug("Infusion(" + i + ")=" + infusion_CLLC2);
							DBG.blogDebug("Has Mutation in Infusion");
							infusion_CLLC = infusion_CLLC2;
							num2 = 1;
						}
					}
				}
			}
			if (num3 < 0)
			{
				DBG.blogDebug("inherit Effect");
				effect_CLLC = (Effect_CLLC)inheritValue((int)extraEffectCreature, (int)dad_effect);
			}
			if (num2 < 0)
			{
				DBG.blogDebug("inherit Infusion");
				infusion_CLLC = (Infusion_CLLC)inheritValue((int)infusionCreature, (int)dad_infusion);
			}
			if (!isEgg)
			{
				AllTameable.CLLC.CLLC.SetExtraEffectCreature(component, effect_CLLC);
				AllTameable.CLLC.CLLC.SetInfusionCreature(component, infusion_CLLC);
				return;
			}
			DBG.blogDebug("Effect=" + effect_CLLC);
			DBG.blogDebug("Infusion=" + infusion_CLLC);
			ItemDrop component3 = ((Component)this).gameObject.GetComponent<ItemDrop>();
			ItemData itemData = component3.m_itemData;
			Utils2.addOrUpdateCustomData(itemData.m_customData, "ExtraEffect", effect_CLLC.ToString());
			Utils2.addOrUpdateCustomData(itemData.m_customData, "Infusion", infusion_CLLC.ToString());
			if ((int)effect_CLLC + (int)infusion_CLLC > 0)
			{
				DBG.blogDebug("Set stack size 1");
				itemData.m_shared.m_maxStackSize = 1;
			}
			component3.Save();
		}

		public static Effect_CLLC iDropGetEff(ItemDrop iDrop)
		{
			Effect_CLLC result = Effect_CLLC.None;
			if (Object.op_Implicit((Object)(object)iDrop))
			{
				DBG.blogDebug("Has iDrop");
				if (iDrop.m_itemData.m_customData.TryGetValue("ExtraEffect", out var value))
				{
					DBG.blogDebug("Custom Value=" + value);
					if (Enum.TryParse<Effect_CLLC>(value, out var result2))
					{
						DBG.blogDebug("GotEffect=" + result2);
						result = result2;
					}
				}
			}
			return result;
		}

		public static Infusion_CLLC iDropGetInf(ItemDrop iDrop)
		{
			Infusion_CLLC result = Infusion_CLLC.None;
			if (Object.op_Implicit((Object)(object)iDrop) && iDrop.m_itemData.m_customData.TryGetValue("Infusion", out var value))
			{
				DBG.blogDebug("Custom Value=" + value);
				if (Enum.TryParse<Infusion_CLLC>(value, out var result2))
				{
					DBG.blogDebug("GotInfusion=" + result2);
					result = result2;
				}
			}
			return result;
		}
	}
	public class AllTame_AnimalAI : MonsterAI
	{
		public float m_timeToSafe = 4f;

		public override bool UpdateAI(float dt)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: 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_01f8: Unknown result type (might be due to invalid IL or missing references)
			Enchants.LongUpdateAI((MonsterAI)(object)this);
			if (((BaseAI)this).m_afraidOfFire && ((BaseAI)this).AvoidFire(dt, (Character)null, true))
			{
				return true;
			}
			base.m_updateTargetTimer -= dt;
			if (base.m_updateTargetTimer <= 0f)
			{
				base.m_updateTargetTimer = (Character.IsCharacterInRange(((Component)this).transform.position, 32f) ? 2f : 10f);
				Character val = ((BaseAI)this).FindEnemy();
				if (Object.op_Implicit((Object)(object)val))
				{
					base.m_targetCreature = val;
				}
			}
			if (Object.op_Implicit((Object)(object)((BaseAI)this).m_tamable) && Object.op_Implicit((Object)(object)((BaseAI)this).m_tamable.m_saddle) && ((BaseAI)this).m_tamable.m_saddle.UpdateRiding(dt))
			{
				return true;
			}
			if (Object.op_Implicit((Object)(object)base.m_targetCreature) && base.m_targetCreature.IsDead())
			{
				base.m_targetCreature = null;
			}
			if (Object.op_Implicit((Object)(object)base.m_targetCreature))
			{
				bool flag = ((BaseAI)this).CanSenseTarget(base.m_targetCreature);
				((BaseAI)this).SetTargetInfo(base.m_targetCreature.GetZDOID());
				if (flag)
				{
					((BaseAI)this).SetAlerted(true);
				}
			}
			else
			{
				((BaseAI)this).SetTargetInfo(ZDOID.None);
			}
			if (((BaseAI)this).IsAlerted())
			{
				base.m_timeSinceSensedTargetCreature += dt;
				if (base.m_timeSinceSensedTargetCreature > m_timeToSafe)
				{
					base.m_targetCreature = null;
					((BaseAI)this).SetAlerted(false);
				}
			}
			if ((!((BaseAI)this).IsAlerted() || ((Object)(object)base.m_targetStatic == (Object)null && (Object)(object)base.m_targetCreature == (Object)null)) && ((MonsterAI)this).UpdateConsumeItem((Humanoid)/*isinst with value type is only supported in some contexts*/, dt))
			{
				return true;
			}
			if (Object.op_Implicit((Object)(object)base.m_targetCreature))
			{
				((BaseAI)this).Flee(dt, ((Component)base.m_targetCreature).transform.position);
				base.m_targetCreature.OnTargeted(false, false);
				return true;
			}
			if (Object.op_Implicit((Object)(object)base.m_follow))
			{
				((BaseAI)this).Follow(base.m_follow, dt);
			}
			else
			{
				((BaseAI)this).IdleMovement(dt);
				((BaseAI)this).m_randomMoveUpdateTimer = ((BaseAI)this).m_randomMoveUpdateTimer - dt;
			}
			((BaseAI)this).ChargeStop();
			((BaseAI)this).UpdateRegeneration(dt);
			return true;
		}
	}
	internal class TameListCfg
	{
		public static Dictionary<string, Plugin.TameTable> cfgList2 = new Dictionary<string, Plugin.TameTable>();

		public static string pathcfg;

		public static Plugin.TameTable defaultTable;

		public static void print_tmtbl(string prefname, Plugin.TameTable tbl)
		{
			string text = prefname + ",";
			try
			{
				text = text + tbl.commandable + ",";
				text = text + tbl.tamingTime + ",";
				text = text + tbl.fedDuration + ",";
				text = text + tbl.consumeRange + ",";
				text = text + tbl.consumeSearchInterval + ",";
				text = text + tbl.consumeHeal + ",";
				text = text + tbl.consumeSearchRange + ",";
				text = text + tbl.consumeItems + ",";
				text = text + tbl.changeFaction + ",";
				text = text + tbl.procretion + ",";
				text = text + tbl.maxCreatures + ",";
				text = text + tbl.pregnancyChance + ",";
				text = text + tbl.pregnancyDuration + ",";
				text = text + tbl.growTime + ",";
				text = text + "canmatewithself=" + tbl.canMateWithSelf + ",";
				text = text + tbl.group + ",";
			}
			catch
			{
			}
			DBG.blogDebug(text);
		}

		public static bool create_TamelistCFG()
		{
			string[] files = Directory.GetFiles(Path.GetDirectoryName(Paths.BepInExConfigPath), "AllTameable_TameList*.cfg");
			if (files.Count() > 0)
			{
				DBG.blogWarning("There are already AllTameable_TameList in your config folder, check to make sure they are formatted correctly");
				DBG.blogWarning("The files are:");
				string[] array = files;
				foreach (string o in array)
				{
					DBG.blogWarning(o);
				}
				return false;
			}
			string cfgPath = Plugin.cfgPath;
			StreamReader streamReader = new StreamReader(cfgPath);
			bool flag = false;
			string[] array2 = new string[0];
			DBG.blogDebug("attempt to read meldurson.valheim.AllTameable");
			string text;
			while ((text = streamReader.ReadLine()) != null && !flag)
			{
				text = text.Trim();
				if (text.StartsWith("Settings"))
				{
					text = text.Replace("TRUE", "true").Replace("FALSE", "false").Replace(" ", "");
					array2 = text.Split(new char[1] { '=' })[1].Split(new char[1] { ';' });
					flag = true;
				}
			}
			if (array2.Count() > 0)
			{
				string text2 = Path.Combine(Path.GetDirectoryName(Paths.BepInExConfigPath), Path.GetFileName("AllTameable_TameList_From_Config.cfg"));
				DBG.blogDebug("createfile_path=" + text2);
				string[] array3 = array2;
				foreach (string text3 in array3)
				{
					DBG.blogDebug("entry=" + text3);
				}
				using StreamWriter streamWriter = File.AppendText(text2);
				string[] array4 = array2;
				foreach (string value in array4)
				{
					streamWriter.WriteLine(value);
				}
			}
			else
			{
				string text4 = Path.Combine(Path.GetDirectoryName(Paths.BepInExConfigPath), Path.GetFileName("AllTameable_TameList_From_Default.cfg"));
				DBG.blogDebug("createfile_path=" + text4);
				DBG.blogDebug("Did not find Setting in config, creating from default");
				using StreamWriter streamWriter2 = File.CreateText(text4);
				streamWriter2.Write(loadDefaultConfig());
			}
			return true;
		}

		private static string loadDefaultConfig()
		{
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith("defaultTamelist.txt"));
			string text = "";
			using (Stream stream = executingAssembly.GetManifestResourceStream(name))
			{
				using StreamReader streamReader = new StreamReader(stream);
				text = streamReader.ReadToEnd();
			}
			DBG.blogDebug("result=" + text);
			return text;
		}

		private static void readTamelist(string path)
		{
			StreamReader streamReader = new StreamReader(path);
			defaultTable = new Plugin.TameTable();
			string text;
			while ((text = streamReader.ReadLine()) != null)
			{
				text = text.Trim();
				if (text.Length == 0 || text.StartsWith("#"))
				{
					continue;
				}
				text = text.Replace("TRUE", "true").Replace("FALSE", "false").Replace(";", "")
					.Replace(" ", "")
					.Replace("\t", "");
				string[] array = text.Split(new char[1] { ',' });
				try
				{
					Plugin.TameTable tameTable = ArrToTametable(array);
					if (array[0].StartsWith("*"))
					{
						defaultTable = (Plugin.TameTable)tameTable.Clone();
						print_tmtbl(array[0], tameTable);
						continue;
					}
					Plugin.TameTable tameTable2 = (Plugin.TameTable)tameTable.Clone();
					string[] array2 = SplitMates(array[0]);
					if (array2.Count() > 1)
					{
						DBG.blogDebug("prefablist=" + string.Join(",", array2));
						Plugin.rawMatesList.Add(array[0]);
						SetCompatMates(array2);
						if (array.Count() > 1)
						{
							for (int i = 0; i < array2.Count(); i++)
							{
								if (!cfgList2.ContainsKey(array2[i]))
								{
									cfgList2.Add(array2[i], tameTable2);
									print_tmtbl(array2[i], tameTable2);
									DBG.blogInfo("succesfully added " + array2[i] + " with mates " + string.Join(", ", array2));
								}
							}
						}
						else
						{
							DBG.blogDebug("Skipping tame, added mates");
						}
					}
					else if (!cfgList2.ContainsKey(array[0]))
					{
						cfgList2.Add(array[0], tameTable2);
						print_tmtbl(array[0], tameTable2);
						DBG.blogInfo("succesfully added " + array[0] + " to the tametable");
					}
					else
					{
						DBG.blogWarning(array[0] + " is already in the tametable");
					}
				}
				catch
				{
					DBG.blogWarning("Failed to add tametablecfg for " + array[0]);
				}
			}
		}

		public static bool Init()
		{
			bool flag = false;
			defaultTable = new Plugin.TameTable();
			cfgList2.Clear();
			string[] files = Directory.GetFiles(Path.GetDirectoryName(Paths.BepInExConfigPath), "AllTameable_TameList*.cfg");
			string[] array = files;
			foreach (string text in array)
			{
				if (!File.Exists(text))
				{
					DBG.blogDebug("Failed to Load: " + text);
					continue;
				}
				DBG.blogInfo("Loaded: " + text.Split(new char[1] { Path.DirectorySeparatorChar }).Last());
				flag = true;
				readTamelist(text);
			}
			if (!flag)
			{
				return false;
			}
			DBG.blogDebug("rawmateslist=" + string.Join(",", Plugin.rawMatesList));
			DBG.blogDebug("rawtradelist= " + string.Join(",", Plugin.rawTradesList));
			Plugin.cfgList = cfgList2;
			return true;
		}

		public static void SetCompatMates(string[] matelist)
		{
			for (int i = 0; i < matelist.Count(); i++)
			{
				List<string> list = new List<string>();
				for (int j = 0; j < matelist.Count(); j++)
				{
					if (i != j)
					{
						list.Add(matelist[j]);
					}
				}
				if (Plugin.CompatMatesList.ContainsKey(matelist[i]))
				{
					foreach (string item in list)
					{
						Plugin.CompatMatesList[matelist[i]].Add(item);
					}
				}
				else
				{
					Plugin.CompatMatesList.Add(matelist[i], list);
				}
				DBG.blogInfo("succesfully Mated " + matelist[i] + " with mates " + string.Join(", ", list));
			}
		}

		public static void UnpackAndOverwriteMates()
		{
			DBG.blogDebug("Unpacking Mates");
			Plugin.CompatMatesList = new Dictionary<string, List<string>>();
			string[] array = Plugin.rawMatesList.ToArray();
			string[] array2 = array;
			foreach (string fullstr in array2)
			{
				SetCompatMates(SplitMates(fullstr));
			}
			DBG.blogDebug("Mates Unpacked");
		}

		public static void UnpackAndOverwriteTrades()
		{
			DBG.blogDebug("Unpacking Trades");
			Plugin.RecruitList = new Dictionary<string, List<TradeAmount>>();
			List<string> rawTradesList = Plugin.rawTradesList;
			foreach (string item in rawTradesList)
			{
				AddTradeList(item.Split(new char[1] { ',' })[0], item.Split(new char[1] { ',' })[1], fromServer: true);
			}
			DBG.blogDebug("Trades Unpacked");
		}

		public static string[] SplitMates(string fullstr)
		{
			string[] array = new string[0];
			if (!fullstr.Contains(":"))
			{
				array.Append(fullstr);
				return array;
			}
			return fullstr.Split(new char[1] { ':' });
		}

		public static Plugin.TameTable ArrToTametable(string[] arr)
		{
			Plugin.TameTable tmtbl;
			try
			{
				if (arr[1].ToLower() == "trade")
				{
					tmtbl = (Plugin.TameTable)defaultTable.Clone();
					tmtbl.tamingTime = -2f;
					tmtbl.consumeItems = "";
					tmtbl.procretion = false;
					AddTradeList(arr[0], arr[2], fromServer: false);
					return tmtbl;
				}
			}
			catch
			{
			}
			int num = arr.Length;
			tmtbl = (Plugin.TameTable)defaultTable.Clone();
			string text = "Failed Setting: ";
			string text2 = text;
			bool flag = false;
			for (int i = 1; i <= num; i++)
			{
				string text3 = "";
				try
				{
					string text4 = arr[i];
					if (text4.Length == 0)
					{
						continue;
					}
					string text5 = i.ToString();
					if (arr[i].Contains("="))
					{
						flag = true;
						string[] array = arr[i].Split(new char[1] { '=' });
						string text6 = array[0];
						text4 = array[1];
						text5 = text6;
						string[] source = new string[11]
						{
							"tamingTime", "fedDuration", "consumeRange", "consumeSearchInterval", "consumeHeal", "consumeSearchRange", "maxCreatures", "pregnancyChance", "pregnancyDuration", "growTime",
							"size"
						};
						text3 = text6 + ", ";
						if (source.Contains(text6))
						{
							PropertyInfo property = tmtbl.GetType().GetProperty(text6, BindingFlags.Instance | BindingFlags.Public);
							if (null != property && property.CanWrite)
							{
								property.SetValue(tmtbl, float.Parse(text4, CultureInfo.InvariantCulture.NumberFormat), null);
							}
							else
							{
								DBG.blogWarning("could not write value " + text6);
							}
						}
						else
						{
							switch (text6)
							{
							case "consumeItems":
								tmtbl.consumeItems = text4;
								break;
							case "group":
								tmtbl.group = text4;
								break;
							case "offspringOnly":
								if (!isValidBool(text4))
								{
									text += "offspringOnly(not true or false), ";
								}
								tmtbl.offspringOnly = text4 != "false";
								break;
							case "changeFaction":
								if (!isValidBool(text4))
								{
									text += "changeFaction(not true or false), ";
								}
								tmtbl.changeFaction = text4 == "true";
								break;
							case "commandable":
								if (!isValidBool(text4))
								{
									text += "commandable(not true or false), ";
								}
								tmtbl.commandable = text4 != "false";
								break;
							case "procretion":
								if (!isValidBool(text4))
								{
									text += "procretion(not true or false), ";
								}
								if (text4 == "overwrite")
								{
									tmtbl.procretion = true;
									tmtbl.procretionOverwrite = true;
								}
								else
								{
									tmtbl.procretion = text4 == "true";
								}
								break;
							case "canMateWithSelf":
								if (!isValidBool(text4))
								{
									text += "canMateWithSelf(not true or false), ";
								}
								tmtbl.canMateWithSelf = text4 == "true";
								break;
							case "specificOffspring":
							{
								Plugin.TameTable tameTable = tmtbl;
								tameTable.specificOffspringString = tameTable.specificOffspringString + "," + text4;
								break;
							}
							case "egg":
								tmtbl.eggValue = text4;
								break;
							case "offspringName":
								tmtbl.offspringName = text4;
								break;
							case "requiredWorldKeys":
								tmtbl.requiredWorldKeys = text4;
								break;
							}
						}
					}
					if (flag)
					{
						continue;
					}
					switch (text5)
					{
					case "1":
					case "commandable":
						text3 = "commandable, ";
						tmtbl.commandable = text4 != "false";
						if (!isValidBool(text4) || float.Parse(text4) > 0f)
						{
							text += "commandable(not true or false), ";
						}
						break;
					case "2":
					case "tamingTime":
						text3 = "tamingTime, ";
						tmtbl.tamingTime = float.Parse(text4);
						break;
					case "3":
					case "fedDuration":
						text3 = "fedDuration, ";
						tmtbl.fedDuration = float.Parse(text4);
						break;
					case "4":
					case "consumeRange":
						text3 = "consumeRange, ";
						tmtbl.consumeRange = float.Parse(text4);
						break;
					case "5":
					case "consumeSearchInterval":
						text3 = "consumeSearchInterval, ";
						tmtbl.consumeSearchInterval = float.Parse(text4);
						break;
					case "6":
					case "consumeHeal":
						text3 = "consumeHeal, ";
						tmtbl.consumeHeal = float.Parse(text4);
						break;
					case "7":
					case "consumeSearchRange":
						text3 = "consumeSearchRange, ";
						tmtbl.consumeSearchRange = float.Parse(text4);
						break;
					case "8":
					case "consumeItems":
						text3 = "consumeItems, ";
						tmtbl.consumeItems = text4;
						break;
					case "9":
					case "changeFaction":
						text3 = "changeFaction, ";
						tmtbl.changeFaction = text4 == "true";
						if (!isValidBool(text4))
						{
							text += "changeFaction(not true or false), ";
						}
						break;
					case "10":
					case "procretion":
						text3 = "procretion, ";
						if (text4 == "overwrite")
						{
							tmtbl.procretion = true;
							tmtbl.procretionOverwrite = true;
						}
						else
						{
							tmtbl.procretion = text4 == "true";
						}
						if (!isValidBool(text4))
						{
							text += "procretion(not true or false), ";
						}
						break;
					case "11":
					case "maxCreatures":
						text3 = "maxCreatures, ";
						tmtbl.maxCreatures = int.Parse(text4);
						break;
					case "12":
					case "pregnancyChance":
						text3 = "pregnancyChance, ";
						tmtbl.pregnancyChance = float.Parse(text4, CultureInfo.InvariantCulture.NumberFormat);
						break;
					case "13":
					case "pregnancyDuration":
						text3 = "pregnancyDuration, ";
						tmtbl.pregnancyDuration = float.Parse(text4);
						break;
					case "14":
					case "growTime":
						text3 = "growTime, ";
						tmtbl.growTime = float.Parse(text4);
						break;
					default:
						text3 = "Failed and set to Default";
						DBG.blogDebug("failed, set default");
						break;
					}
				}
				catch
				{
					text += text3;
				}
			}
			try
			{
				if (float.Parse(arr[1]) == -1f)
				{
					tmtbl = arr.Select((string Array) => new Plugin.TameTable
					{
						tamingTime = float.Parse(arr[1]),
						group = tmtbl.group
					}).ToList()[0];
					return tmtbl;
				}
			}
			catch
			{
			}
			return tmtbl;
		}

		public static bool isValidBool(string bool_str)
		{
			if ((bool_str == "true") | (bool_str == "false"))
			{
				return true;
			}
			return false;
		}

		public static void AddTradeList(string creaturename, string rawstr, bool fromServer)
		{
			string[] array = rawstr.Split(new char[1] { ':' });
			List<TradeAmount> list = new List<TradeAmount>();
			string[] array2 = array;
			foreach (string text in array2)
			{
				string[] array3 = text.Split(new char[1] { '=' });
				TradeAmount tradeAmount = new TradeAmount();
				tradeAmount.tradeItem = array3[0];
				try
				{
					tradeAmount.tradeAmt = int.Parse(array3[1]);
				}
				catch
				{
					tradeAmount.tradeAmt = 1;
					DBG.blogWarning(array3[1] + " is not a valid amount for trade, setting amount to 1");
				}
				list.Add(tradeAmount);
			}
			string[] array4 = SplitMates(creaturename);
			if (array4.Count() == 0)
			{
				array4 = new string[1] { creaturename };
			}
			for (int j = 0; j < array4.Count(); j++)
			{
				if (!Plugin.RecruitList.ContainsKey(array4[j]))
				{
					Plugin.RecruitList.Add(array4[j], list);
					if (!fromServer)
					{
						Plugin.rawTradesList.Add(array4[j] + "," + rawstr);
					}
					DBG.blogDebug("Trades:" + array4[j] + "," + rawstr);
				}
				else
				{
					DBG.blogWarning("Already tradelist set for " + array4[j]);
				}
			}
		}

		static TameListCfg()
		{
			string? directoryName = Path.GetDirectoryName(Paths.BepInExConfigPath);
			char directorySeparatorChar = Path.DirectorySeparatorChar;
			pathcfg = directoryName + directorySeparatorChar + "AllTameable_TameList.cfg";
		}
	}
	internal static class BetterTameHover
	{
		public static float max_interact_default = 3.5f;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(ItemDrop), "GetHoverText")]
		private static void ID_GetHoverText(ItemDrop __instance, ref string __result)
		{
			EggGrow component = ((Component)__instance).gameObject.GetComponent<EggGrow>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return;
			}
			Component[] components = ((Component)__instance).gameObject.GetComponents(typeof(Component));
			int num = 999;
			int num2 = 999;
			for (int i = 0; i < components.Length; i++)
			{
				if (((object)components[i]).GetType() == typeof(ItemDrop))
				{
					num = i;
					break;
				}
				if (((object)components[i]).GetType() == typeof(EggGrow))
				{
					num2 = i;
					break;
				}
			}
			if (num <= num2 && Object.op_Implicit((Object)(object)__instance.m_nview) && __instance.m_nview.IsValid())
			{
				bool flag = __instance.m_nview.GetZDO().GetFloat(ZDOVars.s_growStart, 0f) > 0f;
				string text = ((__instance.m_itemData.m_stack > 1) ? "$item_chicken_egg_stacked" : (flag ? "$item_chicken_egg_warm" : "$item_chicken_egg_cold"));
				string text2 = __result;
				int num3 = text2.IndexOf('\n');
				if (num3 > 0)
				{
					__result = text2.Substring(0, num3) + " " + Localization.instance.Localize(text) + text2.Substring(num3);
				}
				setstack(component);
			}
		}

		public static void setstack(EggGrow instance)
		{
			ItemDrop component = ((Component)instance).GetComponent<ItemDrop>();
			if (Object.op_Implicit((Object)(object)component))
			{
				ProcreationInfo.setStackSize(component.m_itemData);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Tameable), "GetHoverText")]
		private static void Tameable_GetHoverText(Tameable __instance, ref string __result)
		{
			if (!Plugin.hasTamingKeysAndLevel(__instance))
			{
				string oldValue = Localization.instance.Localize("$hud_wild");
				__result = __result.Replace(oldValue, "Feral");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Character), "GetHoverText")]
		public static void Char_GetHoverText(Character __instance, ref string __result)
		{
			if (Plugin.useTamingTool.Value)
			{
				GetTamingText(__instance, ref __result);
			}
			GetDNAText(__instance, ref __result);
		}

		public static void GetTamingText(Character __instance, ref string __result)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)((Humanoid)localPlayer).GetCurrentWeapon().m_dropPrefab == (Object)null || !Plugin.toolNames.Contains(((Object)((Humanoid)localPlayer).GetCurrentWeapon().m_dropPrefab).name))
			{
				return;
			}
			Tameable componentInParent = ((Component)__instance).GetComponentInParent<Tameable>();
			string text = "\n";
			if ((Object)(object)componentInParent == (Object)null)
			{
				if (ShowDebug(localPlayer))
				{
					text += "Not tameable \n";
					text = text + "Prefab name is: " + ((Object)__instance).name;
					text = text.Replace("(Clone)", "");
					__result += text;
				}
				return;
			}
			MonsterAI componentInParent2 = ((Component)__instance).GetComponentInParent<MonsterAI>();
			Procreation componentInParent3 = ((Component)__instance).GetComponentInParent<Procreation>();
			bool flag = true;
			if (__instance.m_tamed)
			{
				if (ShowDebug(localPlayer))
				{
					text += ("Prefab is: " + ((Object)__instance).name + ", is commandable= " + componentInParent.m_commandable + "\n").Replace("(Clone)", "");
				}
				if ((Object)(object)componentInParent3 != (Object)null)
				{
					if (componentInParent3.IsDue())
					{
						text += "Is Due ";
						flag = false;
					}
					else if (componentInParent3.IsPregnant())
					{
						text += "Is Pregnant";
						DateTime dateTime = new DateTime(componentInParent3.m_nview.GetZDO().GetLong("pregnant", 0L));
						double num = (double)componentInParent3.m_pregnancyDuration - (ZNet.instance.GetTime() - dateTime).TotalSeconds;
						if (num > 0.0)
						{
							text = text + ": " + (int)num + "s left\n";
						}
						flag = false;
					}
					else if (!componentInParent3.ReadyForProcreation())
					{
						text += "Needs Food to Procreate";
					}
					else
					{
						if (ShowDebug(localPlayer))
						{
							text += GetPregStats(componentInParent3);
							__result += text;
							return;
						}
						switch (getInstNum(componentInParent3)[0])
						{
						case 1:
							text += "Too Crowded\n";
							break;
						default:
							text += "Needs Mate\n";
							break;
						case 0:
							break;
						}
						text = ((!(componentInParent3.m_pregnancyChance < 1f)) ? (text + "Pregnancy chance is too high: " + componentInParent3.m_pregnancyChance + "\n Check the config and reduce") : (text + "Ready to Procreate"));
					}
				}
				else
				{
					text += "Not able to Procreate";
				}
				if (flag)
				{
					text += "\nPossible Consumables: ";
				}
			}
			else
			{
				AllTame_Interactable allTame_Interactable = default(AllTame_Interactable);
				if (((Component)__instance).gameObject.TryGetComponent<AllTame_Interactable>(ref allTame_Interactable))
				{
					text += "Trade to Recruit";
					text += "\nPossible Trades: ";
					int num2 = 20;
					foreach (KeyValuePair<string, int> item in allTame_Interactable.tradelist)
					{
						text = text + item.Value + " " + item.Key + ", ";
						if (text.Length - num2 > 50)
						{
							num2 = text.Length;
							text += "\n";
						}
					}
					text = text.Remove(text.Length - 2) + "\n";
				}
				if (!(componentInParent.m_tamingTime > 0f))
				{
					__result += text;
					return;
				}
				text += "Taming Time: ";
				if (componentInParent.GetRemainingTime() != componentInParent.m_tamingTime)
				{
					text = text + (int)componentInParent.GetRemainingTime() + "s\\";
				}
				text = text + componentInParent.m_tamingTime + "s";
				if (flag)
				{
					text += "\nPossible Consumables: ";
				}
			}
			if (!flag)
			{
				__result += text;
				return;
			}
			int num3 = 15;
			if (componentInParent2.m_consumeItems.Count < num3)
			{
				foreach (ItemDrop consumeItem in componentInParent2.m_consumeItems)
				{
					text = text + consumeItem.m_itemData.m_shared.m_name + ", ";
				}
			}
			else
			{
				int num4 = (int)Mathf.Ceil((float)componentInParent2.m_consumeItems.Count / (float)num3);
				int num5 = (int)Math.Round((float)(componentInParent2.m_consumeItems.Count / num4) + 0.49f);
				int num6 = (int)(Time.fixedTime * 0.63f) % num4 * num5;
				int num7 = num6;
				for (int i = 0; i < num5 && i <= componentInParent2.m_consumeItems.Count; i++)
				{
					text = text + componentInParent2.m_consumeItems[num7].m_itemData.m_shared.m_name + ", ";
					num7++;
				}
			}
			text = Localization.instance.Localize(text);
			foreach (string hidden_foodName in Plugin.hidden_foodNames)
			{
				text = text.Replace(hidden_foodName + ", ", "");
			}
			text = text.Remove(text.Length - 2);
			__result += text;
		}

		public static void GetDNAText(Character character, ref string __result)
		{
			AllTameable.DNA.DNA dNA = default(AllTameable.DNA.DNA);
			if (!Plugin.useDNA || !((Component)character).TryGetComponent<AllTameable.DNA.DNA>(ref dNA))
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			ItemData helmetItem = ((Humanoid)localPlayer).m_helmetItem;
			if (helmetItem == null || ((Object)((Humanoid)localPlayer).m_helmetItem.m_dropPrefab).name != "TamingHat")
			{
				return;
			}
			if (dNA.HoverText.Length > 0)
			{
				__result += dNA.HoverText;
				return;
			}
			float num = Mathf.Min(new float[3] { dNA.R, dNA.G, dNA.B });
			DBG.blogDebug("SettingHoverText");
			string text = "\n";
			if (Plugin.useDNAColor.Value)
			{
				text = text + "<color=red><b> R:" + Math.Round((float)dNA.R / 1.275f, 1) + "%</b></color>,<color=green><b> G:" + Math.Round((float)dNA.G / 1.275f, 1) + "%</b></color>,<color=#0074FF><b> B:" + Math.Round((float)dNA.B / 1.275f, 1) + "%</b></color>\n";
			}
			if (Plugin.useDNATraits.Value)
			{
				text = text + "<color=#15C0D1><b> Speed:" + Math.Round((float)dNA.Speed / 1.275f, 1) + "</b></color>,<color=#00A60D><b> Health:" + Math.Round((float)dNA.Health / 1.275f, 1) + "</b></color>,<color=#6515D1><b> Armor:" + Math.Round(100f / (387f / ((float)dNA.Armor + 64f) - 1.01f), 1) + "</b></color>\n<color=white><b> Size:" + Math.Round(100f * ((float)(dNA.Size * dNA.Size) / 130000f + (float)dNA.Size / 200f + 0.25f), 1) + "</b></color>\n";
			}
			dNA.HoverText = text;
			__result += text;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Player), "FindHoverObject")]
		private static void Prefix(Player __instance, GameObject hover, Character hoverCreature)
		{
			if (Plugin.useTamingTool.Value && Object.op_Implicit((Object)(object)hoverCreature) && (Object)(object)((Humanoid)__instance).GetCurrentWeapon().m_dropPrefab == (Object)(object)ZNetScene.instance.GetPrefab(Plugin.advtoolPrefabName))
			{
				__instance.m_maxInteractDistance = Plugin.increasedInteractDistance.Value;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Player), "FindHoverObject")]
		private static void Postfix(Player __instance, ref GameObject hover, ref Character hoverCreature)
		{
			if (Object.op_Implicit((Object)(object)hoverCreature) && !Object.op_Implicit((Object)(object)hover) && setHoverCreature(__instance, hoverCreature))
			{
				hover = ((Component)hoverCreature).gameObject;
			}
			__instance.m_maxInteractDistance = max_interact_default;
		}

		public static bool setHoverCreature(Player plr, Character hoverChar)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (Vector3.Distance(((Character)plr).m_eye.position, ((Component)hoverChar).transform.position) < plr.m_maxInteractDistance)
			{
				return true;
			}
			return false;
		}

		public static bool ShowDebug(Player plr)
		{
			if (Plugin.debugout.Value && !((Character)plr).IsCrouching())
			{
				return true;
			}
			return false;
		}

		public static int[] getInstNum(Procreation _proc)
		{
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			int[] array = new int[4];
			int num = -10;
			int num2 = -10;
			int num3 = 0;
			bool flag = true;
			try
			{
				GameObject myPrefab = _proc.m_myPrefab;
				bool num4 = myPrefab == null || !Object.op_Implicit((Object)(object)myPrefab);
				myPrefab = _proc.m_offspringPrefab;
				if (num4 | (myPrefab == null || !Object.op_Implicit((Object)(object)myPrefab)))
				{
					DBG.blogDebug("Hover Initialised");
					AllTameable.Genetics.Genetics.InitProcPrefabs(_proc);
				}
				num = SpawnSystem.GetNrOfInstances(_proc.m_myPrefab, ((Component)_proc).gameObject.transform.position, _proc.m_totalCheckRange, false, false);
				num2 = SpawnSystem.GetNrOfInstances(_proc.m_offspringPrefab, ((Component)_proc).gameObject.transform.position, _proc.m_totalCheckRange, false, false);
				num3 = SpawnSystem.GetNrOfInstances(_proc.m_myPrefab, ((Component)_proc).transform.position, _proc.m_partnerCheckRange, false, true);
				flag = num + num2 < _proc.m_maxCreatures && num3 >= 2;
			}
			catch (Exception ex)
			{
				try
				{
					num = Plugin.Safe_GetNrOfInstances(_proc.m_myPrefab, ((Component)_proc).gameObject.transform.position, _proc.m_totalCheckRange, isError: true);
					num2 = Plugin.Safe_GetNrOfInstances(_proc.m_offspringPrefab, ((Component)_proc).gameObject.transform.position, _proc.m_totalCheckRange, isError: true);
					num3 = Plugin.Safe_GetNrOfInstances(_proc.m_myPrefab, ((Component)_proc).transform.position, _proc.m_partnerCheckRange, isError: true, eventCreaturesOnly: false, procreationOnly: true);
					flag = num + num2 < _proc.m_maxCreatures && num3 >= 2;
				}
				catch
				{
					DBG.blogDebug("Error: " + ex.Message);
					DBG.blogDebug("Error: " + ex.StackTrace);
					array[0] = -1;
					return array;
				}
			}
			array[1] = num;
			array[2] = num2;
			array[3] = num3;
			if (flag)
			{
				array[0] = 0;
				return array;
			}
			if (num + num2 > _proc.m_maxCreatures - 1)
			{
				array[0] = 1;
				return array;
			}
			array[0] = 2;
			return array;
		}

		public static string GetPregStats(Procreation _proc)
		{
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			string text = "";
			bool flag = !_proc.m_nview.IsValid() || !_proc.m_nview.IsOwner() || !_proc.m_character.IsTamed();
			text = text + "isValid: " + !flag;
			text = text + "\nPregchance= " + _proc.m_pregnancyChance;
			text = text + "\nIsNotAlerted= " + !_proc.m_baseAI.IsAlerted();
			text = text + "\nIsNotHungry= " + !_proc.m_tameable.IsHungry();
			text = text + "\nCheckRandomVal: " + (Rando