Decompiled source of Beyondthepen v1.0.1

Beyondthepen.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Beyondthepen")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Beyondthepen")]
[assembly: AssemblyTitle("Beyondthepen")]
[assembly: AssemblyVersion("1.0.0.0")]
public class AnimalConfig
{
	public static Dictionary<string, AnimalConfig> AnimalConfigs = new Dictionary<string, AnimalConfig>
	{
		{
			"$enemy_deer",
			new AnimalConfig
			{
				AnimalName = "Deer",
				TamingTime = 600f,
				FedDuration = 600f,
				PregnancyDuration = 600f,
				MaxCreatures = 6,
				PartnerCheckRange = 2f,
				PregnancyChance = 1f,
				SpawnOffset = 2f,
				RequiredLovePoints = 5,
				MinOffspringLevel = 1,
				FoodItems = new List<string> { "Blueberries", "Raspberry", "Cloudberry" }
			}
		},
		{
			"$enemy_hare",
			new AnimalConfig
			{
				AnimalName = "Hare",
				TamingTime = 600f,
				FedDuration = 600f,
				PregnancyDuration = 600f,
				MaxCreatures = 6,
				PartnerCheckRange = 2f,
				PregnancyChance = 0.5f,
				SpawnOffset = 1.5f,
				RequiredLovePoints = 5,
				MinOffspringLevel = 1,
				FoodItems = new List<string> { "Carrot", "Turnip" }
			}
		}
	};

	public string AnimalName { get; set; }

	public float TamingTime { get; set; }

	public float FedDuration { get; set; }

	public float PregnancyDuration { get; set; }

	public int MaxCreatures { get; set; }

	public float PartnerCheckRange { get; set; }

	public float PregnancyChance { get; set; }

	public float SpawnOffset { get; set; }

	public int RequiredLovePoints { get; set; }

	public int MinOffspringLevel { get; set; }

	public List<string> FoodItems { get; set; }

	public static AnimalConfig GetConfig(string animalName, string originalName = null)
	{
		animalName = animalName.Trim().ToLower();
		if (AnimalConfigs.ContainsKey(animalName))
		{
			return AnimalConfigs[animalName];
		}
		if (originalName != null && AnimalConfigs.ContainsKey(originalName.ToLower()))
		{
			return AnimalConfigs[originalName.ToLower()];
		}
		if (animalName.StartsWith("$enemy_"))
		{
			string key = animalName.Substring(7);
			if (AnimalConfigs.ContainsKey(key))
			{
				return AnimalConfigs[key];
			}
		}
		return null;
	}
}
public class CTA : MonoBehaviour, Interactable, TextReceiver
{
	private const float m_playerMaxDistance = 15f;

	private const float m_tameDeltaTime = 3f;

	public float m_fedDuration = 30f;

	public float m_tamingTime = 1800f;

	public bool m_startsTamed;

	public EffectList m_tamedEffect = new EffectList();

	public EffectList m_sootheEffect = new EffectList();

	public EffectList m_petEffect = new EffectList();

	public bool m_commandable;

	public float m_unsummonDistance;

	public float m_unsummonOnOwnerLogoutSeconds;

	public EffectList m_unSummonEffect = new EffectList();

	public SkillType m_levelUpOwnerSkill;

	public float m_levelUpFactor = 1f;

	public float m_lovePoints = 0f;

	public float m_maxLovePoints = 5f;

	public List<string> m_randomStartingName = new List<string>();

	internal Character m_character;

	private CTP m_CTP;

	internal TameableAI m_TameableAI;

	internal ZNetView m_nview;

	private float m_lastPetTime;

	private float m_unsummonTime;

	internal string originalName;

	private void Awake()
	{
		m_nview = ((Component)this).GetComponent<ZNetView>();
		m_character = ((Component)this).GetComponent<Character>();
		m_TameableAI = ((Component)this).GetComponent<TameableAI>();
		m_CTP = ((Component)this).GetComponent<CTP>();
		originalName = m_character.m_name;
		if (m_nview.IsValid())
		{
			string @string = m_nview.GetZDO().GetString(ZDOVars.s_tamedName, originalName);
			m_character.m_name = @string;
			InitializeEffectsFromBoar();
			m_nview.Register<ZDOID, bool, bool>("Command", (Action<long, ZDOID, bool, bool>)RPC_Command);
			m_nview.Register<string, string>("SetName", (Action<long, string, string>)RPC_SetName);
			m_nview.Register("RPC_UnSummon", (Action<long>)RPC_UnSummon);
		}
		AnimalConfig config = AnimalConfig.GetConfig(originalName);
		if (config != null)
		{
			m_tamingTime = config.TamingTime;
			m_fedDuration = config.FedDuration;
			m_maxLovePoints = config.RequiredLovePoints;
		}
	}

	public void Unregister()
	{
		if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
		{
			m_nview.Unregister("Command");
			m_nview.Unregister("SetName");
			m_nview.Unregister("RPC_UnSummon");
		}
	}

	internal void InitializeEffectsFromBoar()
	{
		GameObject prefab = ZNetScene.instance.GetPrefab("Boar");
		if ((Object)(object)prefab != (Object)null)
		{
			Tameable component = prefab.GetComponent<Tameable>();
			if ((Object)(object)component != (Object)null)
			{
				m_petEffect = component.m_petEffect;
				m_tamedEffect = component.m_tamedEffect;
				m_sootheEffect = component.m_sootheEffect;
			}
		}
	}

	public void Update()
	{
		UpdateSummon();
		UpdateSavedFollowTarget();
	}

	public string GetHoverText()
	{
		if (!m_nview.IsValid())
		{
			return "";
		}
		string text = Localization.instance.Localize(m_character.m_name);
		string boundKeyString = ZInput.instance.GetBoundKeyString("Use", false);
		string text2 = "G";
		if (m_character.IsTamed())
		{
			text += Localization.instance.Localize(" ( $hud_tame, " + GetStatusString() + " )");
			text += Localization.instance.Localize("\n[<color=yellow><b>" + boundKeyString + "</b></color>] $hud_pet  [<color=yellow><b>" + text2 + "</b></color>] Follow");
			text += Localization.instance.Localize("\n[<color=yellow><b>Shift + " + boundKeyString + "</b></color>] Rename");
			int @int = m_nview.GetZDO().GetInt(ZDOVars.s_lovePoints, 0);
			int num = (int)m_maxLovePoints;
			text += "\nLove Points: ";
			for (int i = 0; i < @int; i++)
			{
				text += "<color=#ff0000>♥</color>";
			}
			for (int j = @int; j < num; j++)
			{
				text += "<color=#808080>♥</color>";
			}
			if (m_nview.IsValid())
			{
				long @long = m_nview.GetZDO().GetLong(ZDOVars.s_tameLastFeeding, 0L);
				long ticks = ZNet.instance.GetTime().Ticks;
				float fedDuration = m_fedDuration;
				double num2 = (ticks - @long) / 10000000;
				float num3 = Mathf.Clamp01((fedDuration - (float)num2) / fedDuration) * 100f;
				text += $"\nFood Level: {num3:0}%";
			}
			if ((Object)(object)m_CTP != (Object)null && m_CTP.IsPregnant())
			{
				float timeUntilBirth = m_CTP.GetTimeUntilBirth();
				if (timeUntilBirth > 0f)
				{
					TimeSpan timeSpan = TimeSpan.FromSeconds(timeUntilBirth);
					text += $"\nPregnant: {timeSpan.Minutes:D2}:{timeSpan.Seconds:D2}";
				}
			}
			if (ZInput.GetButtonDown("DeerCommand"))
			{
				Command((Humanoid)(object)Player.m_localPlayer);
				return "";
			}
		}
		else
		{
			int tameness = GetTameness();
			text = ((tameness > 0) ? (text + Localization.instance.Localize($" ( Taming Status: {tameness}%, {GetStatusString()} )")) : (text + Localization.instance.Localize(" ( $hud_wild, " + GetStatusString() + " )")));
		}
		return text;
	}

	public string GetStatusString()
	{
		if (((BaseAI)m_TameableAI).IsAlerted())
		{
			return "$hud_tamefrightened";
		}
		if (IsHungry())
		{
			return "$hud_tamehungry";
		}
		if (m_character.IsTamed())
		{
			return "$hud_tamehappy";
		}
		return "$hud_tameinprogress";
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		if (!m_nview.IsValid())
		{
			return false;
		}
		if (hold)
		{
			return false;
		}
		if (!m_character.IsTamed())
		{
			return false;
		}
		if (alt)
		{
			SetName();
			return true;
		}
		if (ZInput.GetButtonDown("Use") && Time.time - m_lastPetTime > 1f)
		{
			m_lastPetTime = Time.time;
			if (m_petEffect != null)
			{
				m_petEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1);
			}
			int @int = m_nview.GetZDO().GetInt(ZDOVars.s_lovePoints, 0);
			if ((float)@int < m_maxLovePoints)
			{
				@int++;
				m_nview.GetZDO().Set(ZDOVars.s_lovePoints, @int, false);
			}
			((Character)user).Message((MessageType)2, m_character.GetHoverName() + " $hud_tamelove", 0, (Sprite)null);
			return true;
		}
		if (ZInput.GetButtonDown("DeerCommand"))
		{
			Command(user);
			return true;
		}
		return false;
	}

	public string GetHoverName()
	{
		if (!m_character.IsTamed())
		{
			return Localization.instance.Localize(m_character.m_name);
		}
		string text = StringExtensionMethods.RemoveRichTextTags(GetText());
		if (text.Length > 0)
		{
			return text;
		}
		return Localization.instance.Localize(m_character.m_name);
	}

	private void SetName()
	{
		if (m_character.IsTamed())
		{
			TextInput.instance.RequestText((TextReceiver)(object)this, "$hud_rename", 10);
		}
	}

	public string GetText()
	{
		if (!m_nview.IsValid())
		{
			return "";
		}
		return CensorShittyWords.FilterUGC(m_nview.GetZDO().GetString(ZDOVars.s_tamedName, ""), (UGCType)4, m_nview.GetZDO().GetString(ZDOVars.s_tamedNameAuthor, ""), 0L);
	}

	public void SetText(string text)
	{
		if (m_nview.IsValid())
		{
			m_nview.InvokeRPC("SetName", new object[2]
			{
				text,
				PrivilegeManager.GetNetworkUserId()
			});
			m_character.m_name = text;
		}
	}

	private void RPC_SetName(long sender, string name, string authorId)
	{
		if (m_nview.IsValid() && m_nview.IsOwner() && m_character.IsTamed())
		{
			m_nview.GetZDO().Set(ZDOVars.s_tamedName, name);
			m_character.m_name = name;
		}
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		if (!m_nview.IsValid())
		{
			return false;
		}
		if (item == null || item.m_shared != null)
		{
		}
		return false;
	}

	internal void ResetFeedingTimer()
	{
		m_nview.GetZDO().Set(ZDOVars.s_tameLastFeeding, ZNet.instance.GetTime().Ticks);
	}

	private void OnDeath()
	{
	}

	private void TamingUpdate()
	{
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		if (m_nview.IsValid() && m_nview.IsOwner() && (!m_character.IsTamed() || !IsHungry()) && !IsHungry() && !((BaseAI)m_TameableAI).IsAlerted())
		{
			m_TameableAI.SetDespawnInDay(despawn: false);
			m_TameableAI.SetEventCreature(despawn: false);
			DecreaseRemainingTime(3f);
			if (GetRemainingTime() <= 0f)
			{
				Tame();
			}
			else
			{
				m_sootheEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1);
			}
		}
	}

	public void Tame()
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		Game.instance.IncrementPlayerStat((PlayerStatType)48, 1f);
		if (m_nview.IsValid() && m_nview.IsOwner() && !m_character.IsTamed())
		{
			m_TameableAI.MakeTame();
			m_tamedEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1);
			Player closestPlayer = Player.GetClosestPlayer(((Component)this).transform.position, 30f);
			if (Object.op_Implicit((Object)(object)closestPlayer))
			{
				((Character)closestPlayer).Message((MessageType)2, m_character.m_name + " $hud_tamedone", 0, (Sprite)null);
			}
		}
	}

	public static void TameAllInArea(Vector3 point, float radius)
	{
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if (!allCharacter.IsPlayer())
			{
				CTA component = ((Component)allCharacter).GetComponent<CTA>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.Tame();
				}
			}
		}
	}

	public void Command(Humanoid user, bool message = true, bool stay = false)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		m_nview.InvokeRPC("Command", new object[3]
		{
			((Character)user).GetZDOID(),
			message,
			stay
		});
		if (m_nview.IsOwner())
		{
			if (!stay && IsFollowingPlayer(user))
			{
				EnablePortalFollower();
			}
			else
			{
				DisablePortalFollower();
			}
		}
	}

	private void EnablePortalFollower()
	{
		if ((Object)(object)((Component)this).gameObject.GetComponent<PortalFollower>() == (Object)null)
		{
			((Component)this).gameObject.AddComponent<PortalFollower>();
		}
	}

	private void DisablePortalFollower()
	{
		PortalFollower component = ((Component)this).gameObject.GetComponent<PortalFollower>();
		if ((Object)(object)component != (Object)null)
		{
			Object.Destroy((Object)(object)component);
		}
	}

	private bool IsFollowingPlayer(Humanoid user)
	{
		return m_character.IsTamed() && (Object)(object)m_TameableAI.GetFollowTarget() == (Object)(object)((Component)user).gameObject;
	}

	private void RPC_Command(long sender, ZDOID characterID, bool message, bool stay)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		Player player = GetPlayer(characterID);
		if ((Object)(object)player == (Object)null)
		{
			return;
		}
		if (Object.op_Implicit((Object)(object)m_TameableAI.GetFollowTarget()))
		{
			m_TameableAI.SetFollowTarget(null);
			((BaseAI)m_TameableAI).SetPatrolPoint();
			if (m_nview.IsOwner())
			{
				m_nview.GetZDO().Set(ZDOVars.s_follow, "");
			}
			((Character)player).Message((MessageType)2, m_character.GetHoverName() + " $hud_tamestay", 0, (Sprite)null);
		}
		else
		{
			((BaseAI)m_TameableAI).ResetPatrolPoint();
			m_TameableAI.SetFollowTarget(((Component)player).gameObject);
			if (m_nview.IsOwner())
			{
				m_nview.GetZDO().Set(ZDOVars.s_follow, player.GetPlayerName());
			}
			((Character)player).Message((MessageType)2, m_character.GetHoverName() + " $hud_tamefollow", 0, (Sprite)null);
		}
	}

	private void UpdateSavedFollowTarget()
	{
		if ((Object)(object)m_TameableAI.GetFollowTarget() != (Object)null || !m_nview.IsOwner())
		{
			return;
		}
		string @string = m_nview.GetZDO().GetString(ZDOVars.s_follow, "");
		if (string.IsNullOrEmpty(@string))
		{
			return;
		}
		foreach (Player allPlayer in Player.GetAllPlayers())
		{
			if (allPlayer.GetPlayerName() == @string)
			{
				Command((Humanoid)(object)allPlayer, message: false);
				return;
			}
		}
		if (m_unsummonOnOwnerLogoutSeconds > 0f)
		{
			m_unsummonTime += Time.fixedDeltaTime;
			if (m_unsummonTime > m_unsummonOnOwnerLogoutSeconds)
			{
				UnSummon();
			}
		}
	}

	public bool IsHungry()
	{
		if ((Object)(object)m_nview == (Object)null)
		{
			return false;
		}
		ZDO zDO = m_nview.GetZDO();
		DateTime dateTime = new DateTime(zDO.GetLong(ZDOVars.s_tameLastFeeding, 0L));
		return (ZNet.instance.GetTime() - dateTime).TotalSeconds > (double)m_fedDuration;
	}

	private void RPC_UnSummon(long sender)
	{
		//IL_0012: 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)
		m_unSummonEffect.Create(((Component)this).gameObject.transform.position, ((Component)this).gameObject.transform.rotation, (Transform)null, 1f, -1);
		if (m_nview.IsValid() && m_nview.IsOwner())
		{
			ZNetScene.instance.Destroy(((Component)this).gameObject);
		}
	}

	private void OnDestroy()
	{
		Unregister();
	}

	private void UpdateSummon()
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		if (m_nview.IsValid() && m_nview.IsOwner() && m_unsummonDistance > 0f && Object.op_Implicit((Object)(object)m_TameableAI))
		{
			GameObject followTarget = m_TameableAI.GetFollowTarget();
			if (Object.op_Implicit((Object)(object)followTarget) && Vector3.Distance(followTarget.transform.position, ((Component)this).gameObject.transform.position) > m_unsummonDistance)
			{
				UnSummon();
			}
		}
	}

	private void UnsummonMaxInstances(int maxInstances)
	{
		if (!m_nview.IsValid() || !m_nview.IsOwner())
		{
			return;
		}
		GameObject followTarget = m_TameableAI.GetFollowTarget();
		string text = null;
		if ((Object)(object)followTarget != (Object)null)
		{
			Player component = followTarget.GetComponent<Player>();
			if ((Object)(object)component != (Object)null)
			{
				text = component.GetPlayerName();
			}
		}
		if (string.IsNullOrEmpty(text))
		{
			return;
		}
		List<Character> allCharacters = Character.GetAllCharacters();
		List<BaseAI> list = new List<BaseAI>();
		foreach (Character item in allCharacters)
		{
			if (!(item.m_name == m_character.m_name))
			{
				continue;
			}
			ZNetView component2 = ((Component)item).GetComponent<ZNetView>();
			if ((Object)(object)component2 == (Object)null)
			{
				continue;
			}
			ZDO zDO = component2.GetZDO();
			if (zDO == null)
			{
				continue;
			}
			string @string = zDO.GetString(ZDOVars.s_follow, "");
			if (!(@string != text))
			{
				TameableAI component3 = ((Component)item).GetComponent<TameableAI>();
				if ((Object)(object)component3 != (Object)null)
				{
					list.Add((BaseAI)(object)component3);
				}
			}
		}
		list.Sort((BaseAI a, BaseAI b) => b.GetTimeSinceSpawned().CompareTo(a.GetTimeSinceSpawned()));
		int num = list.Count - maxInstances;
		for (int i = 0; i < num; i++)
		{
			CTA component4 = ((Component)list[i]).GetComponent<CTA>();
			if ((Object)(object)component4 != (Object)null)
			{
				component4.UnSummon();
			}
		}
		if (num > 0 && Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			((Character)Player.m_localPlayer).Message((MessageType)2, "$hud_maxsummonsreached", 0, (Sprite)null);
		}
	}

	private void UnSummon()
	{
		if (m_nview.IsValid())
		{
			m_nview.InvokeRPC(ZNetView.Everybody, "RPC_UnSummon", Array.Empty<object>());
		}
	}

	private Player GetPlayer(ZDOID characterID)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = ZNetScene.instance.FindInstance(characterID);
		if (Object.op_Implicit((Object)(object)val))
		{
			return val.GetComponent<Player>();
		}
		return null;
	}

	public void DecreaseRemainingTime(float time)
	{
		if (m_nview.IsValid())
		{
			float remainingTime = GetRemainingTime();
			remainingTime -= time;
			if (remainingTime < 0f)
			{
				remainingTime = 0f;
			}
			m_nview.GetZDO().Set(ZDOVars.s_tameTimeLeft, remainingTime);
		}
	}

	public float GetRemainingTime()
	{
		if (!m_nview.IsValid())
		{
			return 0f;
		}
		return m_nview.GetZDO().GetFloat(ZDOVars.s_tameTimeLeft, m_tamingTime);
	}

	public int GetTameness()
	{
		float remainingTime = GetRemainingTime();
		return (int)((1f - Mathf.Clamp01(remainingTime / m_tamingTime)) * 100f);
	}

	public void OnConsumedItem(ItemDrop item)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		if (IsHungry())
		{
			ResetFeedingTimer();
		}
		m_sootheEffect.Create(m_character.GetCenterPoint(), Quaternion.identity, (Transform)null, 1f, -1);
	}
}
public class CTP : MonoBehaviour
{
	private static class ZDOVars
	{
		public const string s_pregnant = "pregnant";

		public const string s_lovePoints = "lovePoints";
	}

	public float m_updateInterval = 10f;

	public float m_totalCheckRange = 10f;

	public int m_maxCreatures = 4;

	public float m_partnerCheckRange = 3f;

	public float m_pregnancyChance = 1f;

	public float m_pregnancyDuration = 10f;

	public int m_requiredLovePoints = 5;

	public float m_spawnOffset = 2f;

	public EffectList m_birthEffects = new EffectList();

	public EffectList m_loveEffects = new EffectList();

	internal int m_minOffspringLevel = 1;

	private ZNetView m_nview;

	private BaseAI m_baseAI;

	internal Character m_character;

	private CTA m_tameable;

	private void Awake()
	{
		m_nview = ((Component)this).GetComponent<ZNetView>();
		m_baseAI = ((Component)this).GetComponent<BaseAI>();
		m_character = ((Component)this).GetComponent<Character>();
		m_tameable = ((Component)this).GetComponent<CTA>();
		AnimalConfig config = AnimalConfig.GetConfig(m_character.m_name);
		if (config != null)
		{
			m_maxCreatures = config.MaxCreatures;
			m_partnerCheckRange = config.PartnerCheckRange;
			m_pregnancyChance = config.PregnancyChance;
			m_pregnancyDuration = config.PregnancyDuration;
			m_spawnOffset = config.SpawnOffset;
			m_requiredLovePoints = config.RequiredLovePoints;
			m_minOffspringLevel = config.MinOffspringLevel;
		}
		((MonoBehaviour)this).InvokeRepeating("Procreate", Random.Range(m_updateInterval, m_updateInterval + m_updateInterval * 0.5f), m_updateInterval);
	}

	private void Procreate()
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0261: Unknown result type (might be due to invalid IL or missing references)
		if (IsPregnant())
		{
			if (!IsDue())
			{
				return;
			}
			ResetPregnancy();
			Vector3 val = ((Component)this).transform.position - ((Component)this).transform.forward * m_spawnOffset;
			GameObject val2 = Object.Instantiate<GameObject>(((Component)this).gameObject, val, Quaternion.LookRotation(-((Component)this).transform.forward, Vector3.up));
			if (!((Object)(object)val2 == (Object)null))
			{
				Character component = val2.GetComponent<Character>();
				if ((Object)(object)component != (Object)null)
				{
					component.SetTamed(m_character.IsTamed());
					component.SetLevel(Mathf.Max(m_minOffspringLevel, m_character.GetLevel()));
				}
				m_birthEffects.Create(val2.transform.position, Quaternion.identity, (Transform)null, 1f, -1);
			}
		}
		else
		{
			if (!ReadyForProcreation())
			{
				return;
			}
			int @int = m_nview.GetZDO().GetInt("lovePoints", 0);
			if (@int < m_requiredLovePoints || m_tameable.IsHungry())
			{
				return;
			}
			int tamedDeerCount = GetTamedDeerCount(((Component)this).transform.position, m_totalCheckRange);
			if (tamedDeerCount >= m_maxCreatures)
			{
				return;
			}
			List<CTA> list = FindNearbyPartners();
			if (list.Count != 0)
			{
				CTA cTA = list[0];
				int int2 = cTA.m_nview.GetZDO().GetInt("lovePoints", 0);
				if (int2 >= m_requiredLovePoints && Random.value <= m_pregnancyChance)
				{
					long ticks = ZNet.instance.GetTime().Ticks;
					m_nview.GetZDO().Set("pregnant", ticks);
					m_nview.GetZDO().Set("lovePoints", 0);
					cTA.m_nview.GetZDO().Set("lovePoints", 0);
					m_loveEffects.Create(((Component)this).transform.position, Quaternion.identity, (Transform)null, 1f, -1);
				}
			}
		}
	}

	private List<CTA> FindNearbyPartners()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		List<CTA> list = new List<CTA>();
		foreach (BaseAI baseAIInstance in BaseAI.BaseAIInstances)
		{
			if ((Object)(object)baseAIInstance != (Object)null && Vector3.Distance(((Component)baseAIInstance).transform.position, ((Component)this).transform.position) <= m_partnerCheckRange)
			{
				CTA component = ((Component)baseAIInstance).GetComponent<CTA>();
				if ((Object)(object)component != (Object)null && component.m_character.IsTamed() && component.m_character.m_name == m_character.m_name)
				{
					list.Add(component);
				}
			}
		}
		return list;
	}

	public bool ReadyForProcreation()
	{
		return m_character.IsTamed() && !IsPregnant() && !m_tameable.IsHungry();
	}

	private void ResetPregnancy()
	{
		m_nview.GetZDO().Set("pregnant", 0L);
	}

	internal bool IsDue()
	{
		long @long = m_nview.GetZDO().GetLong("pregnant", 0L);
		if (@long == 0)
		{
			return false;
		}
		DateTime dateTime = new DateTime(@long);
		TimeSpan timeSpan = TimeSpan.FromSeconds(m_pregnancyDuration);
		DateTime time = ZNet.instance.GetTime();
		return time - dateTime > timeSpan;
	}

	internal bool IsPregnant()
	{
		return m_nview.IsValid() && m_nview.GetZDO().GetLong("pregnant", 0L) != 0;
	}

	private int GetTamedDeerCount(Vector3 position, float range)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		int num = 0;
		foreach (BaseAI baseAIInstance in BaseAI.BaseAIInstances)
		{
			if ((Object)(object)baseAIInstance != (Object)null && Vector3.Distance(position, ((Component)baseAIInstance).transform.position) <= range)
			{
				Character component = ((Component)baseAIInstance).GetComponent<Character>();
				if ((Object)(object)component != (Object)null && ((Object)component).name.Contains("Deer") && component.IsTamed())
				{
					num++;
				}
			}
		}
		return num;
	}

	internal float GetTimeUntilBirth()
	{
		if (!IsPregnant())
		{
			return 0f;
		}
		long @long = m_nview.GetZDO().GetLong("pregnant", 0L);
		DateTime dateTime = new DateTime(@long);
		TimeSpan timeSpan = TimeSpan.FromSeconds(m_pregnancyDuration);
		DateTime time = ZNet.instance.GetTime();
		float num = (float)(timeSpan - (time - dateTime)).TotalSeconds;
		return Mathf.Max(num, 0f);
	}

	private void SetupDefaultEffects()
	{
		GameObject prefab = ZNetScene.instance.GetPrefab("Boar");
		if ((Object)(object)prefab != (Object)null)
		{
			Procreation component = prefab.GetComponent<Procreation>();
			if ((Object)(object)component != (Object)null)
			{
				m_loveEffects = component.m_loveEffects;
				m_birthEffects = component.m_birthEffects;
			}
		}
	}
}
public class PortalFollower : MonoBehaviour
{
	private Character m_character;

	private ZNetView m_nview;

	private Vector3 m_teleportTargetPos;

	private Quaternion m_teleportTargetRot;

	private GameObject playerGameObject;

	private FieldInfo m_bodyField;

	private Rigidbody m_body;

	private void Awake()
	{
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Expected O, but got Unknown
		m_character = ((Component)this).GetComponent<Character>();
		m_nview = ((Component)this).GetComponent<ZNetView>();
		if ((Object)(object)m_nview == (Object)null || (Object)(object)m_character == (Object)null)
		{
			((Behaviour)this).enabled = false;
			return;
		}
		m_bodyField = typeof(Character).GetField("m_body", BindingFlags.Instance | BindingFlags.NonPublic);
		if (m_bodyField != null)
		{
			m_body = (Rigidbody)m_bodyField.GetValue(m_character);
		}
		else
		{
			((Behaviour)this).enabled = false;
		}
	}

	public void UpdateTeleportPosition(Vector3 targetPosition, Quaternion targetRotation, GameObject player)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		m_teleportTargetPos = targetPosition;
		m_teleportTargetRot = targetRotation;
		playerGameObject = player;
		((MonoBehaviour)this).StartCoroutine(UpdateTeleport());
	}

	private IEnumerator UpdateTeleport()
	{
		if (m_nview.IsOwner())
		{
			((Component)m_character).transform.position = m_teleportTargetPos;
			((Component)m_character).transform.rotation = m_teleportTargetRot;
			if ((Object)(object)m_body != (Object)null)
			{
				m_body.velocity = Vector3.zero;
			}
			Vector3 direction = m_teleportTargetRot * Vector3.forward;
			m_character.SetLookDir(direction, 0f);
			((Component)m_character).GetComponent<CTA>()?.m_TameableAI.SetFollowTarget(playerGameObject);
		}
		yield break;
	}
}
public class TameableAI : BaseAI
{
	private enum IdleState
	{
		Patrol,
		Wander,
		Sleep
	}

	private float m_lastDespawnInDayCheck = -9999f;

	private float m_lastEventCreatureCheck = -9999f;

	public Action<ItemDrop> m_onConsumedItem;

	public float m_alertRange = 9999f;

	public bool m_fleeIfHurtWhenTargetCantBeReached = true;

	public float m_fleeUnreachableSinceAttacking = 30f;

	public float m_fleeUnreachableSinceHurt = 20f;

	public bool m_fleeIfNotAlerted;

	public float m_fleeIfLowHealth;

	public float m_fleeTimeSinceHurt = 20f;

	public bool m_fleeInLava = true;

	public bool m_circulateWhileCharging;

	public bool m_circulateWhileChargingFlying;

	public bool m_enableHuntPlayer;

	public bool m_attackPlayerObjects = false;

	public int m_privateAreaTriggerTreshold = 4;

	public float m_interceptTimeMax;

	public float m_interceptTimeMin;

	public float m_maxChaseDistance;

	public float m_minAttackInterval;

	public float m_circleTargetInterval;

	public float m_circleTargetDuration = 5f;

	public float m_circleTargetDistance = 10f;

	public bool m_sleeping;

	public float m_wakeupRange = 5f;

	public bool m_noiseWakeup;

	public float m_maxNoiseWakeupRange = 50f;

	public EffectList m_wakeupEffects = new EffectList();

	public float m_wakeUpDelayMin;

	public float m_wakeUpDelayMax;

	public bool m_avoidLand;

	public List<ItemDrop> m_consumeItems;

	public float m_consumeRange = 1.5f;

	public float m_consumeSearchRange = 20f;

	public float m_consumeSearchInterval = 1f;

	private ItemDrop m_consumeTarget;

	private float m_consumeSearchTimer;

	private static int m_itemMask = 0;

	private bool m_despawnInDay;

	private bool m_eventCreature;

	private Character m_targetCreature;

	private Vector3 m_lastKnownTargetPos = Vector3.zero;

	private float m_timeSinceSensedTargetCreature;

	private float m_unableToAttackTargetTimer;

	private GameObject m_follow;

	private static readonly int s_sleeping = ZSyncAnimation.GetHash("sleeping");

	public CTA m_tamable;

	private CTP m_procreation;

	private bool m_preventAlert = false;

	private bool m_preventFlee = false;

	private IdleState m_currentIdleState;

	private float m_idleStateTimer;

	private Vector3 m_idleTargetPosition;

	private bool m_isSleeping;

	private Player player;

	private bool playerHasBlueberries;

	private float alertDistance = 20f;

	private bool isAfraidOfPlayer;

	private float m_inDangerTimer = 0f;

	public float m_timeToSafe = 4f;

	private bool tamingStarted = false;

	protected override void Awake()
	{
		((BaseAI)this).Awake();
		m_tamable = ((Component)this).GetComponent<CTA>();
		m_procreation = ((Component)this).GetComponent<CTP>();
		AnimalConfig config = AnimalConfig.GetConfig(base.m_character.m_name);
		isAfraidOfPlayer = true;
		if (config == null)
		{
			return;
		}
		m_despawnInDay = base.m_nview.GetZDO().GetBool(ZDOVars.s_despawnInDay, m_despawnInDay);
		m_eventCreature = base.m_nview.GetZDO().GetBool(ZDOVars.s_eventCreature, m_eventCreature);
		if ((Object)(object)m_tamable != (Object)null)
		{
			m_tamable.m_tamingTime = config.TamingTime;
			m_tamable.m_fedDuration = config.FedDuration;
			m_tamable.m_maxLovePoints = config.RequiredLovePoints;
		}
		if ((Object)(object)m_procreation != (Object)null)
		{
			m_procreation.m_pregnancyDuration = config.PregnancyDuration;
			m_procreation.m_maxCreatures = config.MaxCreatures;
			m_procreation.m_partnerCheckRange = config.PartnerCheckRange;
			m_procreation.m_pregnancyChance = config.PregnancyChance;
			m_procreation.m_spawnOffset = config.SpawnOffset;
			m_procreation.m_requiredLovePoints = config.RequiredLovePoints;
			m_procreation.m_minOffspringLevel = config.MinOffspringLevel;
			if (!base.m_character.IsTamed())
			{
				((Behaviour)m_procreation).enabled = false;
			}
		}
		m_consumeItems = new List<ItemDrop>();
		foreach (string foodItem in config.FoodItems)
		{
			ItemDrop val = FindItemByName(foodItem);
			if ((Object)(object)val != (Object)null)
			{
				m_consumeItems.Add(val);
			}
		}
	}

	private ItemDrop FindItemByName(string itemName)
	{
		if ((Object)(object)ObjectDB.instance == (Object)null)
		{
			return null;
		}
		GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(itemName);
		if ((Object)(object)itemPrefab != (Object)null)
		{
			ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
		}
		return null;
	}

	private void Start()
	{
		if (Object.op_Implicit((Object)(object)base.m_nview) && base.m_nview.IsValid() && base.m_nview.IsOwner())
		{
			Character character = base.m_character;
			Humanoid val = (Humanoid)(object)((character is Humanoid) ? character : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				val.EquipBestWeapon((Character)null, (StaticTarget)null, (Character)null, (Character)null);
			}
		}
	}

	public void MakeTame()
	{
		base.m_character.SetTamed(true);
		((BaseAI)this).SetAlerted(false);
		m_targetCreature = null;
		if ((Object)(object)m_procreation != (Object)null)
		{
			((Behaviour)m_procreation).enabled = true;
		}
	}

	protected override void SetAlerted(bool alert)
	{
		if (alert && m_preventAlert)
		{
			alert = false;
		}
		else if (alert)
		{
			m_timeSinceSensedTargetCreature = 0f;
		}
		((BaseAI)this).SetAlerted(alert);
	}

	public GameObject GetFollowTarget()
	{
		return m_follow;
	}

	public void SetFollowTarget(GameObject go)
	{
		m_follow = go;
	}

	public override bool UpdateAI(float dt)
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		if (!((BaseAI)this).UpdateAI(dt))
		{
			return false;
		}
		player = Player.m_localPlayer;
		if ((Object)(object)player == (Object)null)
		{
			return false;
		}
		if (!base.m_character.IsTamed())
		{
			CheckPlayerBlueberryStatus();
		}
		if (isAfraidOfPlayer && !playerHasBlueberries && Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position) < alertDistance && (Object)(object)m_tamable != (Object)null && !base.m_character.IsTamed() && m_tamable.GetTameness() == 0)
		{
			FleeFromPlayer(dt);
			return true;
		}
		if (((BaseAI)this).IsAlerted())
		{
			m_inDangerTimer += dt;
			if (m_inDangerTimer > m_timeToSafe)
			{
				((BaseAI)this).SetAlerted(false);
				m_inDangerTimer = 0f;
			}
		}
		if (playerHasBlueberries || tamingStarted || base.m_character.IsTamed())
		{
			if ((Object)(object)m_tamable != (Object)null && !base.m_character.IsTamed())
			{
				tamingStarted = true;
				UpdateTaming(dt);
			}
			if ((Object)(object)m_tamable != (Object)null && m_tamable.IsHungry())
			{
				UpdateConsumeItem(base.m_character, dt);
			}
		}
		if (HandleFollowRoutine(dt))
		{
			return true;
		}
		if (HandleIdleRoutine(dt))
		{
			return true;
		}
		return true;
	}

	public void SetPlayerHasBlueberries(bool hasBlueberries)
	{
		playerHasBlueberries = hasBlueberries;
	}

	private void CheckPlayerBlueberryStatus()
	{
		playerHasBlueberries = HasTamingItem(player);
	}

	private void FleeFromPlayer(float dt)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		((BaseAI)this).SetAlerted(true);
		Vector3 val = ((Component)this).transform.position - ((Component)player).transform.position;
		Vector3 val2 = ((Vector3)(ref val)).normalized * alertDistance;
		Vector3 val3 = ((Component)this).transform.position + val2;
		((BaseAI)this).MoveTo(dt, val3, 0f, true);
	}

	private bool HasTamingItem(Player player)
	{
		if (m_consumeItems == null || m_consumeItems.Count == 0)
		{
			return false;
		}
		Inventory inventory = ((Humanoid)player).GetInventory();
		foreach (ItemData allItem in inventory.GetAllItems())
		{
			foreach (ItemDrop consumeItem in m_consumeItems)
			{
				if (allItem.m_shared.m_name == consumeItem.m_itemData.m_shared.m_name && allItem.m_stack > 0)
				{
					return true;
				}
			}
		}
		return false;
	}

	private bool HandleIdleRoutine(float dt)
	{
		if ((Object)(object)m_tamable != (Object)null && base.m_character.IsTamed() && (Object)(object)m_follow == (Object)null)
		{
			UpdateIdleBehavior(dt);
			return true;
		}
		return false;
	}

	private bool HandleFollowRoutine(float dt)
	{
		if ((Object)(object)m_follow != (Object)null)
		{
			FollowTarget(dt);
			return true;
		}
		return false;
	}

	private void UpdateTaming(float dt)
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)m_tamable == (Object)null) && !((BaseAI)this).IsAlerted() && !m_tamable.IsHungry())
		{
			m_tamable.DecreaseRemainingTime(3f * dt);
			m_tamable.m_sootheEffect.Create(((Component)base.m_character).transform.position, ((Component)base.m_character).transform.rotation, (Transform)null, 1f, -1);
			if (m_tamable.GetRemainingTime() <= 0f)
			{
				m_tamable.Tame();
				m_preventAlert = false;
				m_preventFlee = false;
			}
		}
	}

	private bool UpdateConsumeItem(Character character, float dt)
	{
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		if (m_consumeItems == null || m_consumeItems.Count == 0)
		{
			return false;
		}
		m_consumeSearchTimer += dt;
		if (m_consumeSearchTimer > m_consumeSearchInterval)
		{
			m_consumeSearchTimer = 0f;
			m_consumeTarget = FindClosestConsumableItem(m_consumeSearchRange);
			if ((Object)(object)m_consumeTarget == (Object)null)
			{
				return false;
			}
		}
		if ((Object)(object)m_consumeTarget != (Object)null && ((BaseAI)this).MoveTo(dt, ((Component)m_consumeTarget).transform.position, m_consumeRange, false))
		{
			((BaseAI)this).LookAt(((Component)m_consumeTarget).transform.position);
			if (((BaseAI)this).IsLookingAt(((Component)m_consumeTarget).transform.position, 20f, false) && m_consumeTarget.RemoveOne())
			{
				base.m_animator.SetTrigger("consume");
				m_tamable?.OnConsumedItem(m_consumeTarget);
				m_consumeTarget = null;
			}
		}
		return true;
	}

	public void SetPreventAlertAndFlee(bool prevent)
	{
		m_preventAlert = prevent;
		m_preventFlee = prevent;
	}

	private ItemDrop FindClosestConsumableItem(float maxRange)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		if (m_itemMask == 0)
		{
			m_itemMask = LayerMask.GetMask(new string[1] { "item" });
		}
		Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, maxRange, m_itemMask);
		ItemDrop result = null;
		float num = float.MaxValue;
		Collider[] array2 = array;
		foreach (Collider val in array2)
		{
			if (!Object.op_Implicit((Object)(object)val.attachedRigidbody))
			{
				continue;
			}
			ItemDrop component = ((Component)val.attachedRigidbody).GetComponent<ItemDrop>();
			if ((Object)(object)component != (Object)null && CanConsume(component.m_itemData) && ((BaseAI)this).HavePath(((Component)component).transform.position))
			{
				float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)component).transform.position);
				if (num2 < num)
				{
					result = component;
					num = num2;
				}
			}
		}
		return result;
	}

	private bool CanConsume(ItemData item)
	{
		foreach (ItemDrop consumeItem in m_consumeItems)
		{
			if (consumeItem.m_itemData.m_shared.m_name == item.m_shared.m_name)
			{
				return true;
			}
		}
		return false;
	}

	public void SetDespawnInDay(bool despawn)
	{
		m_despawnInDay = despawn;
		base.m_nview.GetZDO().Set(ZDOVars.s_despawnInDay, despawn);
	}

	public bool DespawnInDay()
	{
		if (Time.time - m_lastDespawnInDayCheck > 4f)
		{
			m_lastDespawnInDayCheck = Time.time;
			m_despawnInDay = base.m_nview.GetZDO().GetBool(ZDOVars.s_despawnInDay, m_despawnInDay);
		}
		return m_despawnInDay;
	}

	private void UpdateIdleBehavior(float dt)
	{
		m_idleStateTimer -= dt;
		if (m_idleStateTimer <= 0f)
		{
			m_currentIdleState = (IdleState)Random.Range(0, 3);
			switch (m_currentIdleState)
			{
			case IdleState.Patrol:
				SetPatrolTarget();
				m_idleStateTimer = Random.Range(10f, 20f);
				break;
			case IdleState.Wander:
				SetWanderTarget();
				m_idleStateTimer = Random.Range(5f, 10f);
				break;
			case IdleState.Sleep:
				SetSleeping(isSleeping: true);
				m_idleStateTimer = Random.Range(20f, 40f);
				break;
			}
		}
		switch (m_currentIdleState)
		{
		case IdleState.Patrol:
			Patrol(dt);
			break;
		case IdleState.Wander:
			Wander(dt);
			break;
		case IdleState.Sleep:
			Sleep();
			break;
		}
	}

	private void SetPatrolTarget()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = Random.insideUnitSphere * 10f;
		val.y = 0f;
		m_idleTargetPosition = ((Component)base.m_character).transform.position + val;
	}

	private void Patrol(float dt)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		if (Vector3.Distance(((Component)base.m_character).transform.position, m_idleTargetPosition) > 1f)
		{
			((BaseAI)this).MoveTo(dt, m_idleTargetPosition, 0f, false);
		}
		else
		{
			m_idleStateTimer = 0f;
		}
	}

	private void SetWanderTarget()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = Random.insideUnitSphere * 5f;
		val.y = 0f;
		m_idleTargetPosition = ((Component)base.m_character).transform.position + val;
	}

	private void Wander(float dt)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		if (Vector3.Distance(((Component)base.m_character).transform.position, m_idleTargetPosition) > 1f)
		{
			((BaseAI)this).MoveTo(dt, m_idleTargetPosition, 0f, false);
		}
		else
		{
			m_idleStateTimer = 0f;
		}
	}

	private void Sleep()
	{
		if (!m_isSleeping)
		{
			base.m_animator.SetBool("sleeping", true);
			m_isSleeping = true;
		}
	}

	private void WakeUp()
	{
		base.m_animator.SetBool("sleeping", false);
		m_isSleeping = false;
	}

	public void SetEventCreature(bool despawn)
	{
		m_eventCreature = despawn;
		base.m_nview.GetZDO().Set(ZDOVars.s_eventCreature, despawn);
	}

	public bool IsEventCreature()
	{
		if (Time.time - m_lastEventCreatureCheck > 4f)
		{
			m_lastEventCreatureCheck = Time.time;
			m_eventCreature = base.m_nview.GetZDO().GetBool(ZDOVars.s_eventCreature, m_eventCreature);
		}
		return m_eventCreature;
	}

	private void FollowTarget(float dt)
	{
		//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_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)m_follow != (Object)null)
		{
			Vector3 position = m_follow.transform.position;
			float num = Vector3.Distance(((Component)this).transform.position, position);
			float num2 = 10f;
			float num3 = 3f;
			bool flag = num > num2;
			if (num < num3)
			{
				((BaseAI)this).StopMoving();
			}
			else
			{
				((BaseAI)this).MoveTo(dt, position, 0f, flag);
			}
		}
	}

	private void SetSleeping(bool isSleeping)
	{
		if (isSleeping && !m_isSleeping)
		{
			base.m_animator.SetBool("sleeping", true);
			m_isSleeping = true;
		}
		else if (!isSleeping && m_isSleeping)
		{
			base.m_animator.SetBool("sleeping", false);
			m_isSleeping = false;
		}
	}
}
namespace Beyondthepen;

[BepInPlugin("com.L3ca.Beyondthepen", "Beyond The Pen", "1.0.1")]
public class DeerTamingPlugin : BaseUnityPlugin
{
	private Harmony harmony;

	private Dictionary<string, ConfigEntry<float>> tamingTimes = new Dictionary<string, ConfigEntry<float>>();

	private Dictionary<string, ConfigEntry<float>> fedDurations = new Dictionary<string, ConfigEntry<float>>();

	private Dictionary<string, ConfigEntry<float>> pregnancyDurations = new Dictionary<string, ConfigEntry<float>>();

	private Dictionary<string, ConfigEntry<int>> maxCreatures = new Dictionary<string, ConfigEntry<int>>();

	private Dictionary<string, ConfigEntry<float>> partnerCheckRanges = new Dictionary<string, ConfigEntry<float>>();

	private Dictionary<string, ConfigEntry<float>> pregnancyChances = new Dictionary<string, ConfigEntry<float>>();

	private Dictionary<string, ConfigEntry<float>> spawnOffsets = new Dictionary<string, ConfigEntry<float>>();

	private Dictionary<string, ConfigEntry<int>> requiredLovePoints = new Dictionary<string, ConfigEntry<int>>();

	private Dictionary<string, ConfigEntry<int>> minOffspringLevels = new Dictionary<string, ConfigEntry<int>>();

	private bool tamingLogicApplied = false;

	public static List<Character> NearbyAnimals = new List<Character>();

	public bool TamingLogicApplied
	{
		get
		{
			return tamingLogicApplied;
		}
		private set
		{
			tamingLogicApplied = value;
		}
	}

	public static DeerTamingPlugin Instance { get; private set; }

	private void Awake()
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		harmony = new Harmony("com.L3ca.deertamingmod");
		harmony.PatchAll();
		foreach (KeyValuePair<string, AnimalConfig> animalConfig in AnimalConfig.AnimalConfigs)
		{
			string key = animalConfig.Key;
			AnimalConfig value = animalConfig.Value;
			tamingTimes[key] = ((BaseUnityPlugin)this).Config.Bind<float>(value.AnimalName + " Config", "Taming Time", value.TamingTime, "Taming time for " + value.AnimalName + ".");
			fedDurations[key] = ((BaseUnityPlugin)this).Config.Bind<float>(value.AnimalName + " Config", "Fed Duration", value.FedDuration, "Fed duration for " + value.AnimalName + ".");
			pregnancyDurations[key] = ((BaseUnityPlugin)this).Config.Bind<float>(value.AnimalName + " Config", "Pregnancy Duration", value.PregnancyDuration, "Pregnancy duration for " + value.AnimalName + ".");
			maxCreatures[key] = ((BaseUnityPlugin)this).Config.Bind<int>(value.AnimalName + " Config", "Max Creatures", value.MaxCreatures, "Max creatures for " + value.AnimalName + ".");
			partnerCheckRanges[key] = ((BaseUnityPlugin)this).Config.Bind<float>(value.AnimalName + " Config", "Partner Check Range", value.PartnerCheckRange, "Partner check range for " + value.AnimalName + ".");
			pregnancyChances[key] = ((BaseUnityPlugin)this).Config.Bind<float>(value.AnimalName + " Config", "Pregnancy Chance", value.PregnancyChance, "Pregnancy chance for " + value.AnimalName + ".");
			spawnOffsets[key] = ((BaseUnityPlugin)this).Config.Bind<float>(value.AnimalName + " Config", "Spawn Offset", value.SpawnOffset, "Spawn offset for " + value.AnimalName + ".");
			requiredLovePoints[key] = ((BaseUnityPlugin)this).Config.Bind<int>(value.AnimalName + " Config", "Required Love Points", value.RequiredLovePoints, "Required love points for " + value.AnimalName + ".");
			minOffspringLevels[key] = ((BaseUnityPlugin)this).Config.Bind<int>(value.AnimalName + " Config", "Min Offspring Level", value.MinOffspringLevel, "Minimum offspring level for " + value.AnimalName + ".");
			tamingTimes[key].SettingChanged += OnConfigChanged;
			fedDurations[key].SettingChanged += OnConfigChanged;
			pregnancyDurations[key].SettingChanged += OnConfigChanged;
			maxCreatures[key].SettingChanged += OnConfigChanged;
			partnerCheckRanges[key].SettingChanged += OnConfigChanged;
			pregnancyChances[key].SettingChanged += OnConfigChanged;
			spawnOffsets[key].SettingChanged += OnConfigChanged;
			requiredLovePoints[key].SettingChanged += OnConfigChanged;
			minOffspringLevels[key].SettingChanged += OnConfigChanged;
		}
		ApplyNewConfigValues();
	}

	private void Start()
	{
		((MonoBehaviour)this).StartCoroutine(InitializeMod());
	}

	private void OnConfigChanged(object sender, EventArgs e)
	{
		ApplyNewConfigValues();
	}

	private void ApplyNewConfigValues()
	{
		TameableAI[] array = Object.FindObjectsOfType<TameableAI>();
		foreach (TameableAI tameableAI in array)
		{
			CTA component = ((Component)tameableAI).GetComponent<CTA>();
			if ((Object)(object)component != (Object)null)
			{
				AnimalConfig config = AnimalConfig.GetConfig(component.m_character.m_name);
				if (config != null)
				{
					string name = component.m_character.m_name;
					component.m_tamingTime = tamingTimes[name].Value;
					component.m_fedDuration = fedDurations[name].Value;
				}
			}
			CTP component2 = ((Component)tameableAI).GetComponent<CTP>();
			if ((Object)(object)component2 != (Object)null)
			{
				AnimalConfig config2 = AnimalConfig.GetConfig(component2.m_character.m_name);
				if (config2 != null)
				{
					string name2 = component2.m_character.m_name;
					component2.m_pregnancyDuration = pregnancyDurations[name2].Value;
				}
			}
			SetAnimalFood(tameableAI, ((Component)tameableAI).GetComponent<Character>().m_name);
		}
	}

	private void SetAnimalFood(TameableAI TameableAI, string animalName)
	{
		if ((Object)(object)TameableAI == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
		{
			return;
		}
		AnimalConfig config = AnimalConfig.GetConfig(animalName);
		if (config == null)
		{
			return;
		}
		List<ItemDrop> list = new List<ItemDrop>();
		foreach (string foodItem in config.FoodItems)
		{
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(foodItem);
			if ((Object)(object)itemPrefab != (Object)null)
			{
				ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null)
				{
					list.Add(component);
				}
			}
		}
		if (list.Count > 0)
		{
			TameableAI.m_consumeItems = list;
		}
	}

	private IEnumerator InitializeMod()
	{
		while ((Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
		{
			yield return null;
		}
		foreach (AnimalConfig animalConfig in AnimalConfig.AnimalConfigs.Values)
		{
			ModifyAnimalPrefab(animalConfig.AnimalName);
		}
		((MonoBehaviour)this).StartCoroutine(CheckForAnimals());
	}

	private IEnumerator CheckForAnimals()
	{
		while (true)
		{
			Player player = Player.m_localPlayer;
			if ((Object)(object)player != (Object)null)
			{
				bool hasBlueberries = HasTamingItem(player);
				List<BaseAI> animals = FindNearbyAnimals(((Component)player).transform.position, 20f);
				foreach (BaseAI animal in animals)
				{
					TameableAI tameableAI = ((Component)animal).GetComponent<TameableAI>();
					if ((Object)(object)tameableAI != (Object)null)
					{
						tameableAI.SetPlayerHasBlueberries(hasBlueberries);
					}
				}
			}
			yield return (object)new WaitForSeconds(5f);
		}
	}

	private List<BaseAI> FindNearbyAnimals(Vector3 position, float range)
	{
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		List<BaseAI> list = new List<BaseAI>();
		foreach (BaseAI baseAIInstance in BaseAI.BaseAIInstances)
		{
			if (Vector3.Distance(((Component)baseAIInstance).transform.position, position) <= range)
			{
				list.Add(baseAIInstance);
			}
		}
		return list;
	}

	public void ModifyAnimalPrefab(string animalName)
	{
		GameObject prefab = ZNetScene.instance.GetPrefab(animalName);
		if (!((Object)(object)prefab == (Object)null))
		{
			ZNetView component = prefab.GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null)
			{
				component = prefab.AddComponent<ZNetView>();
			}
			MonsterAI component2 = prefab.GetComponent<MonsterAI>();
			if ((Object)(object)component2 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component2);
			}
			Tameable component3 = prefab.GetComponent<Tameable>();
			if ((Object)(object)component3 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component3);
			}
			Procreation component4 = prefab.GetComponent<Procreation>();
			if ((Object)(object)component4 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component4);
			}
			AnimalAI component5 = prefab.GetComponent<AnimalAI>();
			if ((Object)(object)component5 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component5);
			}
			TameableAI component6 = prefab.GetComponent<TameableAI>();
			if ((Object)(object)component6 == (Object)null)
			{
				component6 = prefab.AddComponent<TameableAI>();
			}
			CTA cTA = prefab.GetComponent<CTA>();
			if ((Object)(object)cTA == (Object)null)
			{
				cTA = prefab.AddComponent<CTA>();
			}
			CTP cTP = prefab.GetComponent<CTP>();
			if ((Object)(object)cTP == (Object)null)
			{
				cTP = prefab.AddComponent<CTP>();
			}
			AnimalConfig config = AnimalConfig.GetConfig(animalName);
			if (config != null)
			{
				cTA.m_tamingTime = config.TamingTime;
				cTA.m_fedDuration = config.FedDuration;
				cTP.m_pregnancyDuration = config.PregnancyDuration;
			}
		}
	}

	private bool HasTamingItem(Player player)
	{
		Inventory inventory = ((Humanoid)player).GetInventory();
		foreach (ItemData allItem in inventory.GetAllItems())
		{
			if (allItem.m_shared.m_name == "$item_animal_bait" && allItem.m_stack > 0)
			{
				return true;
			}
		}
		return false;
	}

	public void CategorizeNearbyAnimals(Vector3 playerPosition, float range, out List<BaseAI> wildAnimals, out List<BaseAI> tamedAnimals)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		wildAnimals = new List<BaseAI>();
		tamedAnimals = new List<BaseAI>();
		foreach (BaseAI baseAIInstance in BaseAI.BaseAIInstances)
		{
			if (!((Object)(object)baseAIInstance != (Object)null))
			{
				continue;
			}
			float num = Vector3.Distance(playerPosition, ((Component)baseAIInstance).transform.position);
			if (!(num <= range))
			{
				continue;
			}
			Character component = ((Component)baseAIInstance).GetComponent<Character>();
			if ((Object)(object)component != (Object)null)
			{
				if (component.IsTamed())
				{
					tamedAnimals.Add(baseAIInstance);
				}
				else
				{
					wildAnimals.Add(baseAIInstance);
				}
			}
		}
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		((MonoBehaviour)this).StopAllCoroutines();
	}
}
[HarmonyPatch(typeof(Character), "GetHoverText")]
public static class Character_GetHoverText_Patch
{
	private static bool Prefix(Character __instance, ref string __result)
	{
		string animalName = Localization.instance.Localize(__instance.m_name);
		CTA component = ((Component)__instance).GetComponent<CTA>();
		if ((Object)(object)component == (Object)null)
		{
			return true;
		}
		AnimalConfig config = AnimalConfig.GetConfig(animalName, component?.originalName);
		if (config != null)
		{
			__result = component.GetHoverText();
			return false;
		}
		return true;
	}
}
[HarmonyPatch(typeof(ZInput), "Initialize")]
public static class ZInput_Initialize_Patch
{
	public static void Postfix()
	{
		FieldInfo field = typeof(ZInput).GetField("m_buttons", BindingFlags.Instance | BindingFlags.NonPublic);
		Dictionary<string, ButtonDef> dictionary = (Dictionary<string, ButtonDef>)field.GetValue(ZInput.instance);
		if (!dictionary.ContainsKey("DeerCommand"))
		{
			ZInput.instance.AddButton("DeerCommand", (Key)21, 0f, 0f, true, false);
		}
	}
}
[HarmonyPatch(typeof(Player))]
[HarmonyPatch("TeleportTo")]
public static class Player_PatchGetAnimals
{
	public static List<Character> NearbyAnimals = new List<Character>();

	public static void Prefix(Player __instance)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		NearbyAnimals.Clear();
		List<Character> list = new List<Character>();
		Character.GetCharactersInRange(((Component)__instance).transform.position, 20f, list);
		foreach (Character item in list)
		{
			CTA component = ((Component)item).GetComponent<CTA>();
			if (item.IsTamed() && (Object)(object)component != (Object)null && (Object)(object)component.m_TameableAI.GetFollowTarget() == (Object)(object)((Component)__instance).gameObject)
			{
				NearbyAnimals.Add(item);
			}
		}
	}
}
[HarmonyPatch(typeof(Player))]
[HarmonyPatch("UpdateTeleport")]
public static class Player_PatchUpdateTeleport
{
	private static void Postfix(ref bool ___m_teleporting, ref float ___m_teleportTimer, ref Vector3 ___m_teleportTargetPos, ref Quaternion ___m_teleportTargetRot)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		if (!___m_teleporting || !(___m_teleportTimer > 2f))
		{
			return;
		}
		Vector3 val2 = default(Vector3);
		foreach (Character nearbyAnimal in Player_PatchGetAnimals.NearbyAnimals)
		{
			if (!((Object)(object)nearbyAnimal == (Object)null))
			{
				Vector2 val = Random.insideUnitCircle * 2f;
				((Vector3)(ref val2))..ctor(val.x, 0f, val.y);
				Vector3 position = ___m_teleportTargetPos + val2;
				((Component)nearbyAnimal).transform.position = position;
				((Component)nearbyAnimal).transform.rotation = ___m_teleportTargetRot;
				nearbyAnimal.SetLookDir(___m_teleportTargetRot * Vector3.forward, 0f);
				((MonoBehaviour)Player.m_localPlayer).StartCoroutine(ConfirmTeleport(nearbyAnimal, ___m_teleportTargetPos, ___m_teleportTargetRot));
			}
		}
		Player_PatchGetAnimals.NearbyAnimals.Clear();
	}

	private static IEnumerator ConfirmTeleport(Character animal, Vector3 targetPosition, Quaternion targetRotation)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		((Component)animal).transform.position = targetPosition;
		((Component)animal).transform.rotation = targetRotation;
		Rigidbody animalBody = ((Component)animal).GetComponent<Rigidbody>();
		if ((Object)(object)animalBody != (Object)null)
		{
			animalBody.velocity = Vector3.zero;
		}
		yield break;
	}
}