Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Beyondthepen v1.0.1
Beyondthepen.dll
Decompiled a year agousing 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; } }