Please disclose if any significant portion of your mod was created 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 HeyBooBoo v1.1.0
plugins\HeyBooBoo\TameableBears.dll
Decompiled 2 days agousing System; 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 Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("TameableBears")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("TameableBears")] [assembly: AssemblyTitle("TameableBears")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TameableBears { [DisallowMultipleComponent] public class BearBabySizer : MonoBehaviour { public static ConfigEntry<float> BabyScale; public static ConfigEntry<float> GrowTime; private const string KeyBabyStart = "bear_baby_start"; private bool _decided; private Vector3 _babyScale = Vector3.one; private void Awake() { //IL_0001: 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) //IL_002a: Unknown result type (might be due to invalid IL or missing references) _babyScale = Vector3.one * Mathf.Max(0.05f, BabyScale?.Value ?? 0.3f); } private void Update() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_00c5: Unknown result type (might be due to invalid IL or missing references) if (!_decided) { Decide(); } ZNetView component = ((Component)this).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } long num = component.GetZDO().GetLong("bear_baby_start", 0L); if (num != 0L) { float num2 = Mathf.Max(1f, GrowTime?.Value ?? 1800f); float num3 = Mathf.Clamp01((float)((ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds / (double)num2)); Vector3 val = ((num3 <= 0f) ? _babyScale : Vector3.Lerp(_babyScale, Vector3.one, num3)); if (((Component)this).transform.localScale != val) { ((Component)this).transform.localScale = val; } if (num3 >= 1f) { Debug.Log((object)("[TameableBears] [BabySizer] " + ((Object)((Component)this).gameObject).name + ": finished growing to full size.")); Object.Destroy((Object)(object)this); } } } private void Decide() { Tameable component = ((Component)this).GetComponent<Tameable>(); BaseAI component2 = ((Component)this).GetComponent<BaseAI>(); ZNetView component3 = ((Component)this).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null || !component3.IsValid()) { return; } TimeSpan timeSinceSpawned = component2.GetTimeSinceSpawned(); bool flag = component.IsTamed(); if (component3.GetZDO().GetLong("bear_baby_start", 0L) != 0L) { _decided = true; Debug.Log((object)("[TameableBears] [BabySizer] " + ((Object)((Component)this).gameObject).name + ": born earlier (zdo key set), resuming growth from started ticks.")); } else if (flag && timeSinceSpawned.TotalSeconds <= 30.0) { if (component3.IsOwner()) { component3.GetZDO().Set("bear_baby_start", ZNet.instance.GetTime().Ticks); } _decided = true; Debug.Log((object)$"[TameableBears] [BabySizer] {((Object)((Component)this).gameObject).name}: newborn detected (age={timeSinceSpawned.TotalSeconds:F1}s, tamed=true), shrinking to baby size."); } else if (timeSinceSpawned.TotalSeconds > 30.0) { Debug.Log((object)$"[TameableBears] [BabySizer] {((Object)((Component)this).gameObject).name}: adult bear (age={timeSinceSpawned.TotalSeconds:F1}s, tamed={flag}), leaving full size."); Object.Destroy((Object)(object)this); } } } internal static class BreedingConfig { public static ConfigEntry<bool> Enabled; public static ConfigEntry<float> FedDuration; public static ConfigEntry<int> MaxCreatures; public static ConfigEntry<float> TotalCheckRange; public static ConfigEntry<float> PartnerCheckRange; public static ConfigEntry<float> PregnancyChance; public static ConfigEntry<int> RequiredLovePoints; public static ConfigEntry<float> PregnancyDuration; public static ConfigEntry<float> UpdateInterval; public static ConfigEntry<bool> Debug; } public static class Breeding { public static string TargetPrefabName; public static void ApplyOverrides(GameObject bear, Tameable tameable, Procreation procreation) { if (BreedingConfig.Enabled != null && BreedingConfig.Enabled.Value) { tameable.m_fedDuration = BreedingConfig.FedDuration.Value; procreation.m_updateInterval = BreedingConfig.UpdateInterval.Value; procreation.m_totalCheckRange = BreedingConfig.TotalCheckRange.Value; procreation.m_maxCreatures = BreedingConfig.MaxCreatures.Value; procreation.m_partnerCheckRange = BreedingConfig.PartnerCheckRange.Value; procreation.m_pregnancyChance = BreedingConfig.PregnancyChance.Value; procreation.m_pregnancyDuration = BreedingConfig.PregnancyDuration.Value; procreation.m_requiredLovePoints = BreedingConfig.RequiredLovePoints.Value; } } } [HarmonyPatch(typeof(Procreation), "Procreate")] internal static class Procreate_DebugPatch { private static readonly Dictionary<int, float> LastLog = new Dictionary<int, float>(); private const float ThrottleSeconds = 20f; private static void Postfix(Procreation __instance) { //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0142: 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) if (BreedingConfig.Debug == null || !BreedingConfig.Debug.Value) { return; } ZNetView component = ((Component)__instance).GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null || !component.IsValid()) { return; } GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(component.GetZDO().GetPrefab()) : null); string text = (((Object)(object)val != (Object)null) ? ((Object)val).name : null); if (string.IsNullOrEmpty(Breeding.TargetPrefabName) || text != Breeding.TargetPrefabName) { return; } Tameable component2 = ((Component)__instance).GetComponent<Tameable>(); if (!((Object)(object)component2 == (Object)null) && component2.IsTamed()) { float time = Time.time; if (!LastLog.TryGetValue(((Object)__instance).GetInstanceID(), out var value) || !(time - value < 20f)) { LastLog[((Object)__instance).GetInstanceID()] = time; BaseAI component3 = ((Component)__instance).GetComponent<BaseAI>(); Vector3 position = ((Component)__instance).transform.position; long num = component.GetZDO().GetLong(ZDOVars.s_pregnant, 0L); bool flag = num != 0; bool flag2 = flag && (ZNet.instance.GetTime() - new DateTime(num)).TotalSeconds > (double)__instance.m_pregnancyDuration; int num2 = (((Object)(object)val != (Object)null) ? SpawnSystem.GetNrOfInstances(val, position, __instance.m_totalCheckRange, false, false) : (-1)); int num3 = (((Object)(object)val != (Object)null) ? SpawnSystem.GetNrOfInstances(val, position, __instance.m_partnerCheckRange, false, true) : (-1)); Debug.Log((object)$"[TameableBears] [Breeding] {text}: owner={component.IsOwner()} tamed={true} hungry={component2.IsHungry()} alert={(Object)(object)component3 != (Object)null && component3.IsAlerted()} love={__instance.GetLovePoints()}/{__instance.m_requiredLovePoints} pregnant={flag} due={flag2} pair={num3} total={num2}/{__instance.m_maxCreatures} (tcr={__instance.m_totalCheckRange} pcr={__instance.m_partnerCheckRange})"); } } } } [BepInPlugin("wayfarers.tameablebears", "HeyBooBoo!", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string GUID = "wayfarers.tameablebears"; public const string Name = "HeyBooBoo!"; public const string Version = "1.1.0"; private void Awake() { BearBabySizer.BabyScale = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "BabyScale", 0.3f, "Spawn scale of newborn (bred) bears. 1.0 = adult size."); BearBabySizer.GrowTime = ((BaseUnityPlugin)this).Config.Bind<float>("Growth", "GrowTime", 1800f, "Seconds for a baby bear to grow to full size. 1800 = one Valheim day."); BreedingConfig.Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Breeding", "Enabled", true, "Enable bear breeding."); BreedingConfig.FedDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Breeding", "FedDuration", 7200f, "Seconds a bear stays 'fed' after eating (breeding is blocked while hungry)."); BreedingConfig.MaxCreatures = ((BaseUnityPlugin)this).Config.Bind<int>("Breeding", "MaxCreatures", 30, "Max bears (tamed+wild, incl. cubs) allowed within TotalCheckRange before breeding stops."); BreedingConfig.TotalCheckRange = ((BaseUnityPlugin)this).Config.Bind<float>("Breeding", "TotalCheckRange", 20f, "Radius used for the total-bear count."); BreedingConfig.PartnerCheckRange = ((BaseUnityPlugin)this).Config.Bind<float>("Breeding", "PartnerCheckRange", 30f, "Radius a second tamed bear must be within for a pair."); BreedingConfig.PregnancyChance = ((BaseUnityPlugin)this).Config.Bind<float>("Breeding", "PregnancyChance", 0.25f, "Chance per tick to gain a love point (0..1)."); BreedingConfig.RequiredLovePoints = ((BaseUnityPlugin)this).Config.Bind<int>("Breeding", "RequiredLovePoints", 5, "Love points needed before the bear gets pregnant."); BreedingConfig.PregnancyDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Breeding", "PregnancyDuration", 1800f, "Seconds a bear stays pregnant before giving birth. 1800 = one Valheim day."); BreedingConfig.UpdateInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Breeding", "UpdateInterval", 2f, "Seconds between breeding checks."); BreedingConfig.Debug = ((BaseUnityPlugin)this).Config.Bind<bool>("Breeding", "DebugLog", true, "Log one breeding status line per tamed bear every ~20 seconds."); Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, (string)null); PrefabManager.OnVanillaPrefabsAvailable += MakeBearsTameable; } private void OnDestroy() { PrefabManager.OnVanillaPrefabsAvailable -= MakeBearsTameable; } private void MakeBearsTameable() { GameObject prefab = Cache.GetPrefab<GameObject>("Wolf"); GameObject val = null; string text = null; string[] array = new string[2] { "Bjorn", "Bear" }; foreach (string text2 in array) { GameObject prefab2 = Cache.GetPrefab<GameObject>(text2); if ((Object)(object)prefab2 != (Object)null && (Object)(object)prefab2.GetComponent<MonsterAI>() != (Object)null) { val = prefab2; text = text2; break; } } if ((Object)(object)prefab == (Object)null || (Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Missing prefabs (wolf={(Object)(object)prefab != (Object)null} bear={(Object)(object)val != (Object)null})"); return; } Tameable component = prefab.GetComponent<Tameable>(); MonsterAI component2 = prefab.GetComponent<MonsterAI>(); MonsterAI component3 = val.GetComponent<MonsterAI>(); if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"Missing components (wolfTameable={(Object)(object)component != (Object)null} wolfAI={(Object)(object)component2 != (Object)null} bearAI={(Object)(object)component3 != (Object)null})"); return; } component3.m_consumeItems = new List<ItemDrop>(component2.m_consumeItems); component3.m_consumeRange = component2.m_consumeRange; component3.m_consumeSearchRange = component2.m_consumeSearchRange; component3.m_consumeSearchInterval = component2.m_consumeSearchInterval; if ((Object)(object)val.GetComponent<Tameable>() != (Object)null) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Bear already has a Tameable component; nothing to do."); return; } Tameable val2 = val.AddComponent<Tameable>(); val2.m_tamingTime = component.m_tamingTime; val2.m_fedDuration = component.m_fedDuration; val2.m_commandable = component.m_commandable; val2.m_tameText = component.m_tameText; val2.m_nameBeforeText = component.m_nameBeforeText; val2.m_tamingSpeedMultiplierRange = component.m_tamingSpeedMultiplierRange; val2.m_tamingBoostMultiplier = component.m_tamingBoostMultiplier; val2.m_tamedEffect = component.m_tamedEffect; val2.m_sootheEffect = component.m_sootheEffect; val2.m_petEffect = component.m_petEffect; val2.m_randomStartingName = new List<string>(component.m_randomStartingName); Procreation component4 = prefab.GetComponent<Procreation>(); Procreation component5 = val.GetComponent<Procreation>(); if ((Object)(object)component4 != (Object)null && (Object)(object)component5 == (Object)null) { component5 = val.AddComponent<Procreation>(); component5.m_updateInterval = component4.m_updateInterval; component5.m_totalCheckRange = component4.m_totalCheckRange; component5.m_maxCreatures = component4.m_maxCreatures; component5.m_partnerCheckRange = component4.m_partnerCheckRange; component5.m_pregnancyChance = component4.m_pregnancyChance; component5.m_pregnancyDuration = component4.m_pregnancyDuration; component5.m_requiredLovePoints = component4.m_requiredLovePoints; component5.m_offspring = val; component5.m_minOffspringLevel = component4.m_minOffspringLevel; component5.m_spawnOffset = component4.m_spawnOffset; component5.m_spawnOffsetMax = component4.m_spawnOffsetMax; component5.m_spawnRandomDirection = component4.m_spawnRandomDirection; component5.m_birthEffects = component4.m_birthEffects; component5.m_loveEffects = component4.m_loveEffects; Breeding.TargetPrefabName = text; Breeding.ApplyOverrides(val, val2, component5); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Bears can now breed (pairs of fed, tamed bears produce cubs)."); } if ((Object)(object)val.GetComponent<BearBabySizer>() == (Object)null) { val.AddComponent<BearBabySizer>(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Baby bears spawn small and grow to full size (" + text + ").")); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Bears are now tameable! Feed them raw meat, drop it near them, and wait (like wolves)."); } } }