Decompiled source of AllTameableTamingOverhaul v1.3.9

AllTameable_TamingOverhaul.dll

Decompiled 2 weeks 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 AllTameable;
using AllTameable.AutoFeedAT;
using AllTameable.CLLC;
using AllTameable.DNA;
using AllTameable.Genetics;
using AllTameable.RPC;
using AllTameable.RRRCoreTameable;
using AllTameable.Trading;
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 RRRCore;
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)
	})]
	private static void PostfixHaveRequirementItems(Player __instance, Recipe recipe, bool discover, int qualityLevel)
	{
		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_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;
		}
	}
	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.NrOfItems() > 0)
			{
				for (int num = inventory.m_inventory.Count - 1; num >= 0; num--)
				{
					if (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 Prefix(CharacterDrop __instance)
		{
			if (!__instance.m_character.m_tamed)
			{
				return;
			}
			foreach (Drop drop in __instance.m_drops)
			{
				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)
			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);
				}
				addExtraCommands(ref __result);
			}
		}

		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[2] { "SE_SpeedTame", "SE_Calming" };
			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_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			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);
			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);
				}
			}
		}

		[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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			List<Player> s_players = Player.s_players;
			float num = 0f;
			foreach (Player item in s_players)
			{
				DBG.tryblogDebug("plr id=" + item.GetPlayerName(), "could not get name");
				if (((Character)item).m_nview.IsValid() && !(Vector3.Distance(((Component)item).transform.position, center) > maxdist) && Time.time < ((Character)item).m_nview.GetZDO().GetFloat("SE_SpeedTame", 0f))
				{
					num += 3f;
				}
			}
			return num;
		}

		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 AllTame_AnimalAI : MonsterAI
	{
		public float m_safetime = 8f;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MonsterAI), "UpdateAI")]
		private static bool Prefix(AllTame_AnimalAI __instance, float dt)
		{
			if (typeof(AllTame_AnimalAI) == ((object)__instance).GetType())
			{
				__instance.UpdateAI_AllTameable(dt);
				return false;
			}
			return true;
		}

		private void UpdateAI_AllTameable(float dt)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			if (((BaseAI)this).m_nview.IsOwner())
			{
				((BaseAI)this).UpdateTakeoffLanding(dt);
				if (((BaseAI)this).m_jumpInterval > 0f)
				{
					((BaseAI)this).m_jumpTimer = ((BaseAI)this).m_jumpTimer + dt;
				}
				if (((BaseAI)this).m_randomMoveUpdateTimer > 0f)
				{
					((BaseAI)this).m_randomMoveUpdateTimer = ((BaseAI)this).m_randomMoveUpdateTimer - dt;
				}
				((BaseAI)this).UpdateRegeneration(dt);
				((BaseAI)this).m_timeSinceHurt = ((BaseAI)this).m_timeSinceHurt + dt;
				if (((BaseAI)this).m_afraidOfFire && ((BaseAI)this).AvoidFire(dt, (Character)null, true))
				{
					return;
				}
				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;
					}
				}
				Character character = ((BaseAI)this).m_character;
				Humanoid val2 = (Humanoid)(object)((character is Humanoid) ? character : null);
				if ((Object)(object)base.m_targetCreature != (Object)null && 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)
					{
						((MonsterAI)this).SetAlerted(true);
					}
				}
				else
				{
					((BaseAI)this).SetTargetInfo(ZDOID.None);
				}
				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;
				}
				if (((BaseAI)this).IsAlerted())
				{
					base.m_timeSinceSensedTargetCreature += dt;
					if (base.m_timeSinceSensedTargetCreature > m_safetime)
					{
						base.m_targetCreature = null;
						((MonsterAI)this).SetAlerted(false);
					}
				}
				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);
				}
				else if ((!((BaseAI)this).IsAlerted() || ((Object)(object)base.m_targetStatic == (Object)null && (Object)(object)base.m_targetCreature == (Object)null)) && ((MonsterAI)this).UpdateConsumeItem(val2, dt))
				{
					base.m_aiStatus = "Consume item";
				}
				else if (Object.op_Implicit((Object)(object)base.m_follow))
				{
					((BaseAI)this).Follow(base.m_follow, dt);
					base.m_aiStatus = "Follow";
				}
				else
				{
					((BaseAI)this).IdleMovement(dt);
				}
			}
			else
			{
				((BaseAI)this).m_alerted = ((BaseAI)this).m_nview.GetZDO().GetBool("alert", false);
			}
		}
	}
	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 + ",";
			}
			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 = new Plugin.TameTable();
					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;
							}
						}
					}
					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))
			{
				ItemData itemData = component.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 = itemData.m_stack;
				}
				else
				{
					itemData.m_shared.m_maxStackSize = Math.Max(itemData.m_stack, 20);
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Character), "GetHoverText")]
		private 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 + componentInParent.GetRemainingTime() + "s\\";
				}
				text = text + componentInParent.m_tamingTime + "s";
				if (flag)
				{
					text += "\nPossible Consumables: ";
				}
			}
			if (!flag)
			{
				__result += text;
				return;
			}
			foreach (ItemDrop consumeItem in componentInParent2.m_consumeItems)
			{
				text = text + consumeItem.m_itemData.m_shared.m_name + ", ";
			}
			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: " + (Random.value > _proc.m_pregnancyChance) + "<-if not steady False, then valid";
			bool flag2 = Random.value <= _proc.m_pregnancyChance || _proc.m_baseAI.IsAlerted() || _proc.m_tameable.IsHungry();
			text = text + "\nislessThanPregchance: " + !flag2 + "<-if not steady False, then valid";
			int[] instNum = getInstNum(_proc);
			switch (instNum[0])
			{
			case 0:
				text += "\nLess than max instance: True";
				break;
			case 1:
				text += "\nLess than max instance: False";
				text = text + "\nMax=" + _proc.m_maxCreatures + ", Mates=" + (instNum[1] - 1) + ", Offspring=" + instNum[2];
				break;
			case 2:
				text += "\nLess than max instance: False (needs mate)";
				text = text + "\nReady Mates=" + (instNum[3] - 1) + ", Offspring=" + instNum[2];
				text = text + "\nClosest 3 Creatures within range of " + _proc.m_totalCheckRange + " units are:\n";
				text += GetCloseInstances(((Component)_proc).gameObject, ((Component)_proc).gameObject.transform.position, _proc.m_totalCheckRange);
				break;
			default:
				text += "\nLess than max instance: Error";
				break;
			}
			int @int = _proc.m_nview.GetZDO().GetInt("lovePoints", 0);
			return text + "\nLovePoints: " + @int + " out of " + _proc.m_requiredLovePoints;
		}

		private static string GetCloseInstances(GameObject instance, Vector3 center, float maxRange)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			float num = 999999f;
			float num2 = 999999f;
			float num3 = 999999f;
			string text = "n/a";
			string text2 = "n/a2";
			string text3 = "n/a3";
			BaseAI componentInParent = instance.GetComponentInParent<BaseAI>();
			List<Character> allCharacters = Character.GetAllCharacters();
			foreach (Character item in allCharacters)
			{
				if (!((Object)(object)((Component)item).gameObject == (Object)(object)((Component)componentInParent).gameObject) && !item.IsPlayer() && ((Component)item).GetComponent<ZNetView>().IsValid())
				{
					float num4 = Vector3.Distance(((Component)item).transform.position, instance.transform.position);
					if (num4 < num)
					{
						text = ((Object)item).name;
						num = num4;
						text = ((!item.IsTamed()) ? ((!((Object)(object)((Component)item).gameObject.GetComponent<Tameable>() != (Object)null)) ? (text + "(NotTameable)") : (text + "(Untamed)")) : (text + "(Tamed)"));
					}
					else if (num4 < num2)
					{
						text2 = ((Object)item).name;
						num2 = num4;
						text2 = ((!item.IsTamed()) ? ((!((Object)(object)((Component)item).gameObject.GetComponent<Tameable>() != (Object)null)) ? (text2 + "(NotTameable)") : (text2 + "(Untamed)")) : (text2 + "(Tamed)"));
					}
					else if (num4 < num3)
					{
						text3 = ((Object)item).name;
						num3 = num4;
						text3 = ((!item.IsTamed()) ? ((!((Object)(object)((Component)item).gameObject.GetComponent<Tameable>() != (Object)null)) ? (text3 + "(NotTameable)") : (text3 + "(Untamed)")) : (text3 + "(Tamed)"));
					}
				}
			}
			return (text + ":" + text2 + ":" + text3).Replace("(Clone)", "");
		}
	}
	public static class DBG
	{
		public static void cprt(string s)
		{
			Console.instance.Print(s);
		}

		public static void InfoTL(string s)
		{
			((Character)Player.m_localPlayer).Message((MessageType)1, s, 0, (Sprite)null);
		}

		public static void InfoCT(string s)
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, s, 0, (Sprite)null);
		}

		public static void blogInfo(object o)
		{
			Plugin.logger.LogInfo(o);
		}

		public static void blogWarning(object o)
		{
			Plugin.logger.LogWarning(o);
		}

		public static void blogDebug(object o)
		{
			if (Plugin.debugout.Value)
			{
				Plugin.logger.LogWarning(o);
			}
		}

		public static void tryblogDebug(object o, object o_backup)
		{
			try
			{
				if (Plugin.debugout.Value)
				{
					Plugin.logger.LogWarning(o);
				}
			}
			catch
			{
				Plugin.logger.LogWarning(o_backup);
			}
		}
	}
	public class PetManager : MonoBehaviour
	{
		private static ZNetScene zns;

		private static Tameable wtame;

		public static GameObject Root;

		public static bool isInit;

		public static bool isInit2;

		public static GameObject heartEffectGO;

		public static GameObject DrakeEggPrefab;

		public static GameObject ChickenEggPrefab;

		public static bool SetConstants = false;

		public static bool SetEggs = false;

		public static bool AlteredEggs = false;

		public static List<GameObject> CustomEggs = new List<GameObject>();

		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("MiniOnes");
			Root.transform.SetParent(Plugin.prefabManager.Root.transform);
		}

		public void Clear()
		{
			isInit = false;
			isInit2 = false;
			SetEggs = false;
			CustomEggs.Clear();
		}

		private static string AddCreatures(Dictionary<string, Plugin.TameTable> cfgList)
		{
			string text = "";
			foreach (KeyValuePair<string, Plugin.TameTable> cfg in cfgList)
			{
				string key = cfg.Key;
				if ((Object)(object)zns.GetPrefab(key) == (Object)null)
				{
					DBG.blogWarning("Cant find Prefab Check your name : " + key);
					text = text + key + ",";
				}
				else
				{
					AddTame(zns.GetPrefab(key), cfg.Value);
				}
			}
			return text;
		}

		public static void CheckConst()
		{
			zns = ZNetScene.instance;
			if (!SetConstants)
			{
				wtame = PrefabManager.Instance.GetPrefab("Wolf").GetComponent<Tameable>();
				createHeartEffect();
				ChickenEggPrefab = PrefabManager.Instance.GetPrefab("ChickenEgg");
				DrakeEggPrefab = PrefabManager.Instance.GetPrefab("DragonEgg");
				SetConstants = true;
				PrefabManager.OnVanillaPrefabsAvailable -= CheckConst;
			}
		}

		public static void Init2nd(GameObject init_go)
		{
			isInit2 = true;
			Plugin.PreSetMinis = false;
			CheckConst();
			Dictionary<string, Plugin.TameTable> cfgListFailed = Plugin.cfgListFailed;
			int num = 0;
			int num2 = 0;
			string text = "Failed";
			foreach (KeyValuePair<string, Plugin.TameTable> item in cfgListFailed)
			{
				num2++;
				string key = item.Key;
				if ((Object)(object)zns.GetPrefab(key) != (Object)null)
				{
					AddTame(zns.GetPrefab(key), item.Value);
					if (Utils.GetPrefabName(init_go) == key)
					{
						AddTame(init_go, item.Value);
						DBG.blogDebug("Post Added First Spawn: " + ((Object)init_go).name);
					}
					num++;
					DBG.blogDebug("Post Added " + key);
				}
				else
				{
					text = text + ":" + key;
				}
			}
			if (num2 > 0)
			{
				if (num == num2)
				{
					DBG.blogDebug("Succesfully Post Added " + num + "/" + num2);
				}
				else
				{
					DBG.blogWarning("Failed to Post Add " + (num2 - num) + "/" + num2);
					DBG.blogWarning(text);
				}
			}
			List<string> list = new List<string>(Plugin.PostMakeList);
			foreach (string item2 in list)
			{
				GameObject prefab = zns.GetPrefab(item2);
				Procreation component = prefab.GetComponent<Procreation>();
				component.m_offspring = SpawnMini(prefab);
			}
		}

		public static void UpdatesFromServer()
		{
			TameListCfg.UnpackAndOverwriteMates();
			TameListCfg.UnpackAndOverwriteTrades();
			SetupAllCreatures();
			ObjectDB.instance.UpdateItemHashes();
			DBG.blogInfo("Succesfully Loaded Config from server");
		}

		public static void FixAnimalAI(GameObject go)
		{
			if (!((Object)(object)go.GetComponent<AllTame_AnimalAI>() == (Object)null))
			{
				return;
			}
			DBG.blogDebug("Fixing AI for " + ((Object)go).name);
			zns = ZNetScene.instance;
			wtame = zns.GetPrefab("Wolf").GetComponent<Tameable>();
			MonsterAI component = zns.GetPrefab("Boar").GetComponent<MonsterAI>();
			Humanoid val = default(Humanoid);
			if (!go.TryGetComponent<Humanoid>(ref val))
			{
				val = go.AddComponent<Humanoid>();
				((Character)val).m_eye = go.transform.GetChild(0);
			}
			AnimalAI component2 = go.GetComponent<AnimalAI>();
			Character component3 = go.GetComponent<Character>();
			AllTame_AnimalAI allTame_AnimalAI = go.AddComponent<AllTame_AnimalAI>();
			FieldInfo[] fields = typeof(MonsterAI).GetFields();
			foreach (FieldInfo fieldInfo in fields)
			{
				try
				{
					if ((fieldInfo.GetValue(allTame_AnimalAI) != null) & (fieldInfo.GetValue(component) != fieldInfo.GetValue(allTame_AnimalAI)))
					{
						fieldInfo.SetValue(allTame_AnimalAI, fieldInfo.GetValue(component));
					}
				}
				catch
				{
				}
			}
			FieldInfo[] fields2 = typeof(AnimalAI).GetFields();
			foreach (FieldInfo fieldInfo2 in fields2)
			{
				try
				{
					if ((fieldInfo2.GetValue(allTame_AnimalAI) != null) & (fieldInfo2.GetValue(component2) != fieldInfo2.GetValue(allTame_AnimalAI)))
					{
						fieldInfo2.SetValue(allTame_AnimalAI, fieldInfo2.GetValue(component2));
					}
				}
				catch
				{
				}
			}
			FieldInfo[] fields3 = typeof(Character).GetFields();
			foreach (FieldInfo fieldInfo3 in fields3)
			{
				try
				{
					if ((fieldInfo3.GetValue(val) != null) & (fieldInfo3.GetValue(component3) != fieldInfo3.GetValue(val)))
					{
						fieldInfo3.SetValue(val, fieldInfo3.GetValue(component3));
					}
				}
				catch
				{
				}
			}
			((BaseAI)allTame_AnimalAI).m_character = (Character)(object)val;
			Object.DestroyImmediate((Object)(object)go.GetComponent<AnimalAI>());
			Object.DestroyImmediate((Object)(object)go.GetComponent<Character>());
		}

		public static void SetupAllCreatures()
		{
			isInit = true;
			CheckConst();
			if (!SetEggs)
			{
				SetDNAEggs();
			}
			EggGrow val = default(EggGrow);
			if (Plugin.HatchingEgg.Value)
			{
				AlterEggs();
			}
			else if (DrakeEggPrefab.TryGetComponent<EggGrow>(ref val))
			{
				Object.DestroyImmediate((Object)(object)val);
			}
			AddCreatures(Plugin.cfgList);
			List<GameObject> list = zns.m_prefabs.FindAll((GameObject go) => Object.op_Implicit((Object)(object)go.GetComponent<Tameable>()) && !Plugin.cfgList.ContainsKey(((Object)go).name));
			string text = "";
			AllTameable.DNA.DNA dNA = default(AllTameable.DNA.DNA);
			foreach (GameObject item in list)
			{
				text = text + ((Object)item).name + ",";
				if (!item.TryGetComponent<AllTameable.DNA.DNA>(ref dNA))
				{
					if (Plugin.useDNA)
					{
						item.AddComponent<AllTameable.DNA.DNA>();
					}
				}
				else if (!Plugin.useDNA)
				{
					Object.DestroyImmediate((Object)(object)dNA);
				}
			}
			if (text != "")
			{
				DBG.blogDebug("Modified DNA for existing tames:" + text);
			}
		}

		public static void SetupAllCreatures(GameObject init_go)
		{
			SetupAllCreatures();
			Plugin.cfgList.TryGetValue(Utils.GetPrefabName(init_go.gameObject), out var value);
			AddTame(init_go, value);
		}

		public static void createHeartEffect()
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			DBG.blogDebug("Making HeartEffect");
			heartEffectGO = Object.Instantiate<GameObject>(wtame.m_petEffect.m_effectPrefabs[0].m_prefab, Root.transform);
			DBG.blogDebug("removing child");
			heartEffectGO.transform.GetChild(1).parent = null;
			DBG.blogDebug("Creating new effect");
			EffectData val = new EffectData();
			DBG.blogDebug("setting prefab to go");
			val.m_prefab = heartEffectGO;
			DBG.blogDebug("Created HeartEffect");
		}

		private static void AddTame(GameObject go, Plugin.TameTable tb)
		{
			//IL_04ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b2: Expected O, but got Unknown
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Expected O, but got Unknown
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Expected O, but got Unknown
			try
			{
				if ((Object)(object)go.GetComponent<MonsterAI>() == (Object)null)
				{
					if (!((Object)(object)go.GetComponent<AnimalAI>() != (Object)null))
					{
						DBG.blogWarning(((Object)go).name + " can't be added,Remove it in your cfg");
						return;
					}
					FixAnimalAI(go);
				}
				if (Plugin.useDNA && (Object)(object)go.GetComponent<AllTameable.DNA.DNA>() == (Object)null)
				{
					go.AddComponent<AllTameable.DNA.DNA>();
				}
				if (tb.group != "")
				{
					if ((Object)(object)go.GetComponent<Humanoid>() != (Object)null)
					{
						((Character)go.GetComponent<Humanoid>()).m_group = tb.group;
					}
					else if ((Object)(object)go.GetComponent<Character>() != (Object)null)
					{
						go.GetComponent<Character>().m_group = tb.group;
					}
				}
				else if (!tb.changeFaction)
				{
					if ((Object)(object)go.GetComponent<Humanoid>() != (Object)null)
					{
						((Character)go.GetComponent<Humanoid>()).m_group = ((Object)go).name;
					}
					else if ((Object)(object)go.GetComponent<Character>() != (Object)null)
					{
						go.GetComponent<Character>().m_group = ((Object)go).name;
					}
				}
				if (tb.tamingTime == -1f)
				{
					DBG.blogDebug("Removing Tameable from " + ((Object)go).name);
					if ((Object)(object)go.GetComponent<Tameable>() != (Object)null)
					{
						Object.DestroyImmediate((Object)(object)go.GetComponent<Tameable>());
					}
					if ((Object)(object)go.GetComponent<Procreation>() != (Object)null)
					{
						Object.DestroyImmediate((Object)(object)go.GetComponent<Procreation>());
					}
					return;
				}
				if (tb.tamingTime == -2f)
				{
					DBG.blogDebug("Setting Only Tradeable for  " + ((Object)go).name);
					if ((Object)(object)go.GetComponent<Procreation>() != (Object)null)
					{
						Object.DestroyImmediate((Object)(object)go.GetComponent<Procreation>());
					}
				}
				Tameable val = default(Tameable);
				if (!go.TryGetComponent<Tameable>(ref val))
				{
					val = go.AddComponent<Tameable>();
				}
				MonsterAI component = go.GetComponent<MonsterAI>();
				Humanoid component2 = go.GetComponent<Humanoid>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					findTamedAttackVariants(component2);
				}
				if (Plugin.RecruitList.TryGetValue(((Object)go).name, out var value))
				{
					DBG.blogDebug("Found RecruitList");
					AllTame_Interactable allTame_Interactable = default(AllTame_Interactable);
					if (!go.TryGetComponent<AllTame_Interactable>(ref allTame_Interactable))
					{
						DBG.blogDebug("Adding AllTame_Interactable");
						allTame_Interactable = go.AddComponent<AllTame_Interactable>();
						DBG.blogDebug("Added AllTame_Interactable");
					}
					int num = 0;
					string text = ((Object)go).name + " trades:";
					foreach (TradeAmount item2 in value)
					{
						GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item2.tradeItem);
						if ((Object)(object)itemPrefab == (Object)null)
						{
							DBG.blogWarning("Wrong item name " + item2.tradeItem);
						}
						else
						{
							allTame_Interactable.tradeItems[num] = ((Object)itemPrefab).name;
							allTame_Interactable.tradeAmounts[num] = item2.tradeAmt;
							text = text + item2.tradeItem + ", " + item2.tradeAmt + "; ";
						}
						num++;
					}
					DBG.blogDebug(text);
					Array.Resize(ref allTame_Interactable.tradeItems, value.Count);
					Array.Resize(ref allTame_Interactable.tradeAmounts, value.Count);
				}
				if (((Object)go).name.ToLower().IndexOf("dverger") > -1)
				{
					val.m_petEffect = new EffectList();
					EffectData[] effectPrefabs = (EffectData[])(object)new EffectData[1]
					{
						new EffectData()
					};
					val.m_petEffect.m_effectPrefabs = effectPrefabs;
					val.m_petEffect.m_effectPrefabs[0].m_prefab = ZNetScene.instance.GetPrefab("sfx_dverger_vo_alerted");
				}
				else
				{
					int num2 = 0;
					string text2 = "Effect List: ";
					EffectData[] array = (EffectData[])(object)new EffectData[10];
					EffectData[] effectPrefabs2 = ((BaseAI)component).m_idleSound.m_effectPrefabs;
					EffectData[] array2 = effectPrefabs2;
					foreach (EffectData val2 in array2)
					{
						try
						{
							text2 = text2 + num2 + ":" + ((Object)val2.m_prefab).name;
							array[num2] = val2;
						}
						catch
						{
						}
						num2++;
					}
					int num3 = num2;
					num3 = effectPrefabs2.Length;
					if (((BaseAI)component).m_idleSound.m_effectPrefabs.Length != 0)
					{
						EffectData val3 = new EffectData();
						val3.m_prefab = heartEffectGO;
						array[num3] = val3;
						Array.Resize(ref array, num3 + 1);
						val.m_petEffect.m_effectPrefabs = array;
					}
					else
					{
						val.m_petEffect = wtame.m_petEffect;
					}
				}
				val.m_sootheEffect = wtame.m_sootheEffect;
				val.m_tamedEffect = wtame.m_tamedEffect;
				val.m_commandable = tb.commandable;
				if (tb.commandable)
				{
					DBG.blogDebug(((Object)go).name + " is commandable");
				}
				else
				{
					DBG.blogDebug(((Object)go).name + " is not commandable");
				}
				val.m_tamingTime = tb.tamingTime;
				val.m_fedDuration = tb.fedDuration * Plugin.TamedFedMultiplier.Value;
				component.m_consumeRange = tb.consumeRange;
				component.m_consumeSearchInterval = tb.consumeSearchInterval;
				component.m_consumeSearchRange = tb.consumeSearchRange;
				if (component.m_enableHuntPlayer)
				{
					component.m_wakeupRange = 150f;
					component.m_enableHuntPlayer = false;
				}
				List<string> list = new List<string>();
				tb.consumeItems = tb.consumeItems + ":" + string.Join(":", Plugin.hidden_foodPrefabs);
				DBG.blogDebug("tb.consumeItems=" + tb.consumeItems);
				string[] array3 = tb.consumeItems.Split(new char[1] { ':' });
				string[] array4 = array3;
				if (component.m_consumeItems != null)
				{
					component.m_consumeItems.Clear();
				}
				component.m_consumeItems = new List<ItemDrop>();
				string[] array5 = array4;
				foreach (string item in array5)
				{
					list.Add(item);
				}
				if (!string.IsNullOrEmpty(list[0]) | (list.Count > 1))
				{
					foreach (string item3 in list)
					{
						GameObject itemPrefab2 = ObjectDB.instance.GetItemPrefab(item3);
						if ((Object)(object)itemPrefab2 == (Object)null)
						{
							DBG.blogWarning("Wrong food name :" + item3);
						}
						else
						{
							component.m_consumeItems.Add(itemPrefab2.GetComponent<ItemDrop>());
						}
					}
				}
				else
				{
					DBG.blogInfo("Cannot be tamed by food");
				}
				if (tb.procretion)
				{
					bool flag = true;
					Procreation val4 = default(Procreation);
					if (!go.TryGetComponent<Procreation>(ref val4))
					{
						val4 = go.AddComponent<Procreation>();
						flag = false;
					}
					val4.m_maxCreatures = tb.maxCreatures;
					val4.m_pregnancyChance = tb.pregnancyChance;
					if (val4.m_pregnancyChance > 1f)
					{
						Procreation obj2 = val4;
						obj2.m_pregnancyChance *= 0.01f;
					}
					if (val4.m_pregnancyChance > 1f)
					{
						val4.m_pregnancyChance = 0.66f;
					}
					val4.m_pregnancyDuration = tb.pregnancyDuration;
					if (val4.m_updateInterval < 20f)
					{
						val4.m_updateInterval = 20f;
					}
					val4.m_partnerCheckRange = 4f * tb.size;
					val4.m_totalCheckRange = 10f * tb.size;
					if ((tb.eggValue ?? "") != "")
					{
						bool DrakeEgg = true;
						float hatchtime = 1800f;
						string colorstr = "default";
						float size = 1f;
						parseEggValue(tb.eggValue, ref DrakeEgg, ref hatchtime, ref colorstr, ref size);
						val4.m_offspring = InitEgg(go, tb, hatchtime, DrakeEgg, colorstr, size);
					}
					else if (flag && (Object)(object)val4.m_offspring != (Object)null && !Plugin.CheckHuman(go) && !tb.procretionOverwrite)
					{
						GameObject offspring = val4.m_offspring;
						Growup component3 = offspring.GetComponent<Growup>();
						if (Object.op_Implicit((Object)(object)component3))
						{
							component3.m_growTime = tb.growTime;
						}
						else
						{
							EggGrow component4 = offspring.GetComponent<EggGrow>();
							if (Object.op_Implicit((Object)(object)component4))
							{
								Growup component5 = component4.m_grownPrefab.GetComponent<Growup>();
								if (Object.op_Implicit((Object)(object)component5))
								{
									component5.m_growTime = tb.growTime;
									DBG.blogWarning(((Object)go).name + " has egg as offspring, modified hatched prefab growtime");
								}
								if (Plugin.useDNA && (Object)(object)component4.m_grownPrefab.GetComponent<AllTameable.DNA.DNA>() == (Object)null)
								{
									component4.m_grownPrefab.AddComponent<AllTameable.DNA.DNA>();
								}
							}
							else
							{
								DBG.blogWarning("Failed to set grow time for " + ((Object)go).name);
							}
						}
						if (Plugin.useDNA && (Object)(object)offspring.GetComponent<AllTameable.DNA.DNA>() == (Object)null)
						{
							offspring.AddComponent<AllTameable.DNA.DNA>();
						}
						string name = ((Object)offspring).name;
						int stableHashCode = StringExtensionMethods.GetStableHashCode(name);
						if (zns.m_namedPrefabs.ContainsKey(stableHashCode))
						{
							DBG.blogDebug("Already has " + name + " in ObjectDB, only changing growup time");
						}
						else
						{
							DBG.blogDebug("Had to Register " + name + " in ObjectDB");
							PrefabManager.Instance.RegisterToZNetScene(offspring);
						}
						DBG.blogDebug(((Object)go).name + " already has offspring, modified tameable");
					}
					else if (((Object)go).name == "Hatchling" && Plugin.HatchingEgg.Value)
					{
						val4.m_offspring = DrakeEggPrefab;
					}
					else
					{
						val4.m_offspring = SpawnMini(go);
					}
					if (ZNet.instance.IsServer() & ZNet.instance.IsDedicated())
					{
						GameObject prefab = ZNetScene.instance.GetPrefab(((Object)go).name);
						string text3 = " is not Tameable";
						if (((Behaviour)prefab.GetComponent<Tameable>()).enabled)
						{
							text3 = " is Tameable";
						}
						DBG.blogDebug("******* " + ((Object)prefab).name + text3 + " ********");
					}
				}
				else
				{
					if ((Object)(object)go.GetComponent<Procreation>() != (Object)null)
					{
						Object.DestroyImmediate((Object)(object)go.GetComponent<Procreation>());
					}
					if ((tb.eggValue ?? "") != "")
					{
						bool DrakeEgg2 = true;
						float hatchtime2 = 1800f;
						string colorstr2 = "default";
						float size2 = 1f;
						parseEggValue(tb.eggValue, ref DrakeEgg2, ref hatchtime2, ref colorstr2, ref size2);
						InitEgg(go, tb, hatchtime2, DrakeEgg2, colorstr2, size2);
						Plugin.NoProcEggList.Add(((Object)go).name);
						DBG.blogDebug("Has Egg but no proc, adding to list:" + ((Object)go).name);
					}
					DBG.blogDebug("Added ability to tame to " + ((Object)go).name);
				}
				if (tb.offspringOnly)
				{
					DBG.blogDebug("Removing Tameable from " + ((Object)go).name + " due to only being from procreation");
					if ((Object)(object)go.GetComponent<Tameable>() != (Object)null)
					{
						Object.DestroyImmediate((Object)(object)go.GetComponent<Tameable>());
					}
					if ((Object)(object)go.GetComponent<Procreation>() != (Object)null)
					{
						Object.DestroyImmediate((Object)(object)go.GetComponent<Procreation>());
					}
				}
			}
			catch
			{
				DBG.blogWarning("Failed to add tame to prefab: " + ((Object)go).name + ", Make sure config files are formatted correctly");
			}
		}

		public static GameObject SpawnMini(GameObject prefab, float growup_time = 1800f)
		{
			//IL_010c: 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)
			bool flag = false;
			string text = ((Object)prefab).name;
			bool flag2 = false;
			if (text.Contains("(Clone"))
			{
				text = Utils.GetPrefabName(prefab);
				flag = true;
			}
			GameObject val = Object.Instantiate<GameObject>(zns.GetPrefab(text), Root.transform);
			if (text.Contains("RRRN"))
			{
				flag2 = true;
				if (AllTameable.RRRCoreTameable.RRRCoreTameable.CheckHuman(prefab))
				{
					val = AllTameable.RRRCoreTameable.RRRCoreTameable.HotFixHuman(val);
				}
			}
			string text2 = (flag2 ? "Child" : "Mini");
			((Object)val).name = "Mini" + text;
			string name = ((Object)val).name;
			int stableHashCode = StringExtensionMethods.GetStableHashCode(name);
			if (zns.m_namedPrefabs.ContainsKey(stableHashCode))
			{
				DBG.blogDebug("Already has " + name + " in ObjectDB, changed growup time");
				GameObject prefab2 = zns.GetPrefab(stableHashCode);
				Growup component = prefab2.GetComponent<Growup>();
				component.m_growTime = growup_time;
				return prefab2;
			}
			Transform transform = val.transform;
			transform.localScale *= 0.5f;
			if ((Object)(object)val.GetComponent<Humanoid>() != (Object)null)
			{
				((Character)val.GetComponent<Humanoid>()).m_name = text2 + " " + ((Character)val.GetComponent<Humanoid>()).m_name;
			}
			else
			{
				val.GetComponent<Character>().m_name = text2 + " " + val.GetComponent<Character>().m_name;
			}
			if ((Object)(object)val.GetComponent<MonsterAI>() != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val.GetComponent<MonsterAI>());
			}
			if ((Object)(object)val.GetComponent<VisEquipment>() != (Object)null)
			{
				removeWeaponsFromSets(val);
			}
			if ((Object)(object)val.GetComponent<CharacterDrop>() != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val.GetComponent<CharacterDrop>());
			}
			if ((Object)(object)val.GetComponent<Tameable>() != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val.GetComponent<Tameable>());
			}
			if ((Object)(object)val.GetComponent<Procreation>() != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val.GetComponent<Procreation>());
			}
			if ((Object)(object)val.GetComponent<NpcTalk>() != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)val.GetComponent<NpcTalk>());
			}
			MonsterAI component2 = prefab.GetComponent<MonsterAI>();
			AnimalAI comp = val.AddComponent<AnimalAI>();
			((Component)(object)comp).CopyBroComponet<AnimalAI, MonsterAI>(component2);
			Growup val2 = val.AddComponent<Growup>();
			val2.m_grownPrefab = zns.GetPrefab(text);
			if (Plugin.cfgList.ContainsKey(text))
			{
				val2.m_growTime = Plugin.cfgList[text].growTime;
			}
			else
			{
				val2.m_growTime = growup_time;
			}
			if (!Plugin.PreSetMinis)
			{
				if (zns.m_namedPrefabs.ContainsKey(stableHashCode))
				{
					zns.m_namedPrefabs.Remove(stableHashCode);
				}
				PrefabManager.Instance.RegisterToZNetScene(val);
			}
			else if (!flag)
			{
				PrefabManager.Instance.RegisterToZNetScene(val);
			}
			if ((Object)(object)ZNetScene.instance.GetPrefab(((Object)val).name) != (Object)null)
			{
				DBG.blogDebug("Successfully added Tame and Procreation to " + ((Object)prefab).name);
			}
			return val;
		}

		public static bool findTamedAttackinSpawnAbility(SpawnAbility spawnAbility, ref GameObject[] newSpawnPref, Transform base_go)
		{
			bool result = false;
			GameObject[] spawnPrefab = spawnAbility.m_spawnPrefab;
			newSpawnPref = (GameObject[])(object)new GameObject[spawnPrefab.Length];
			Tameable val = default(Tameable);
			for (int i = 0; i < spawnPrefab.Length; i++)
			{
				if (!Object.op_Implicit((Object)(object)spawnPrefab[i].GetComponent<Character>()))
				{
					newSpawnPref[i] = spawnPrefab[i];
					continue;
				}
				if (SaveAttackPart(spawnPrefab[i], ref newSpawnPref[i], base_go))
				{
					ZDOChanger zDOChanger = newSpawnPref[i].AddComponent<ZDOChanger>();
					zDOChanger.newName = ((Object)newSpawnPref[i]).name.Replace("_tamed", "");
					if (!newSpawnPref[i].TryGetComponent<Tameable>(ref val))
					{
						val = newSpawnPref[i].AddComponent<Tameable>();
					}
					val.m_startsTamed = true;
				}
				result = true;
			}
			return result;
		}

		public static bool SaveAttackPart(GameObject go, ref GameObject copy, Transform base_go)
		{
			string text = ((Object)go).name.Replace("(Clone)", "") + "_tamed";
			int stableHashCode = StringExtensionMethods.GetStableHashCode(text);
			if (zns.m_namedPrefabs.ContainsKey(stableHashCode))
			{
				copy = zns.GetPrefab(stableHashCode);
				return false;
			}
			copy = Object.Instantiate<GameObject>(go, base_go);
			((Object)copy).name = text;
			PrefabManager.Instance.RegisterToZNetScene(copy);
			DBG.blogDebug(((Object)copy).name + " registered to ZNetScene");
			return true;
		}

		public static void findTamedAttackVariants(Humanoid humanoid)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Expected O, but got Unknown
			if (humanoid.m_defaultItems == null)
			{
				return;
			}
			int num = humanoid.m_defaultItems.Length;
			Projectile val = default(Projectile);
			SpawnAbility spawnAbility = default(SpawnAbility);
			SpawnAbility spawnAbility2 = default(SpawnAbility);
			for (int i = 0; i < num; i++)
			{
				if (Plugin.TamedAttackVariants.ContainsKey(((Object)humanoid.m_defaultItems[i]).name))
				{
					continue;
				}
				Transform transform = new GameObject(((Object)humanoid.m_defaultItems[i]).name + "_base").transform;
				((Component)transform).gameObject.SetActive(false);
				bool flag = false;
				bool flag2 = false;
				ItemDrop component = humanoid.m_defaultItems[i].GetComponent<ItemDrop>();
				string text = "0";
				GameObject copy = null;
				if (Object.op_Implicit((Object)(object)component))
				{
					text += "1";
					GameObject attackProjectile = component.m_itemData.m_shared.m_attack.m_attackProjectile;
					if (Object.op_Implicit((Object)(object)attackProjectile))
					{
						text += "2";
						GameObject copy2 = null;
						if (attackProjectile.TryGetComponent<Projectile>(ref val))
						{
							text += "3";
							GameObject spawnOnHit = val.m_spawnOnHit;
							if (Object.op_Implicit((Object)(object)spawnOnHit))
							{
								text += "4";
								GameObject[] newSpawnPref = null;
								if (spawnOnHit.TryGetComponent<SpawnAbility>(ref spawnAbility))
								{
									flag |= findTamedAttackinSpawnAbility(spawnAbility, ref newSpawnPref, transform);
								}
								if (flag && SaveAttackPart(spawnOnHit, ref copy2, transform))
								{
									copy2.GetComponent<SpawnAbility>().m_spawnPrefab = newSpawnPref;
								}
							}
							if (flag && (SaveAttackPart(attackProjectile, ref copy, transform) || flag2))
							{
								copy.GetComponent<Projectile>().m_spawnOnHit = copy2;
							}
						}
						GameObject[] newSpawnPref2 = null;
						if (attackProjectile.TryGetComponent<SpawnAbility>(ref spawnAbility2))
						{
							flag2 |= findTamedAttackinSpawnAbility(spawnAbility2, ref newSpawnPref2, transform);
						}
						if (flag2 && (SaveAttackPart(attackProjectile, ref copy, transform) || flag))
						{
							copy.GetComponent<SpawnAbility>().m_spawnPrefab = newSpawnPref2;
						}
					}
				}
				if (flag || flag2)
				{
					GameObject val2 = Object.Instantiate<GameObject>(humanoid.m_defaultItems[i], transform);
					((Object)val2).name = ((Object)val2).name.Replace("(Clone)", "_tamed");
					ItemDrop component2 = val2.GetComponent<ItemDrop>();
					component2.m_itemData.m_shared.m_attack.m_attackProjectile = copy;
					component2.m_itemData.m_dropPrefab = val2;
					component2.Save();
					ItemManager.Instance.AddItem(new CustomItem(val2, false));
					int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)val2).name);
					if (!ObjectDB.instance.m_itemByHash.ContainsKey(stableHashCode))
					{
						ObjectDB.instance.m_items.Add(val2);
						ObjectDB.instance.m_itemByHash.Add(stableHashCode, val2);
					}
					Plugin.TamedAttackVariants.Add(((Object)humanoid.m_defaultItems[i]).name, val2);
					((Component)transform).transform.parent = Root.transform;
					DBG.blogDebug("New Attack made: " + ((Object)val2).name);
				}
			}
		}

		public static void findTamedAttackVariants_backup(Humanoid humanoid)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if (humanoid.m_defaultItems == null)
			{
				return;
			}
			int num = humanoid.m_defaultItems.Length;
			Projectile val3 = default(Projectile);
			SpawnAbility val5 = default(SpawnAbility);
			Tameable val8 = default(Tameable);
			for (int i = 0; i < num; i++)
			{
				Transform transform = new GameObject(((Object)humanoid.m_defaultItems[i]).name + "_base").transform;
				((Component)transform).gameObject.SetActive(false);
				GameObject val = Object.Instantiate<GameObject>(humanoid.m_defaultItems[i], transform);
				DBG.blogWar