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;
}
}