Decompiled source of balrond MonsterMayehm v0.3.7

plugins/BalrondMonsterMayhem.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using HarmonyLib;
using LitJson2;
using SoftReferenceableAssets;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;
using UpgradeWorld;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Balrond Biomes")]
[assembly: AssemblyDescription("Valheim Game Rework")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Balrond - Worm Works Studio")]
[assembly: AssemblyProduct("Balrond")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("Balrond")]
[assembly: ComVisible(false)]
[assembly: Guid("f405ea1c-ac25-47a3-9aa2-a8f56c14bfd6")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
public static class BalrondHashCompat
{
	private static readonly MethodInfo _getStableHashCodeStringBool;

	private static readonly MethodInfo _getStableHashCodeString;

	private static readonly bool _initialized;

	static BalrondHashCompat()
	{
		try
		{
			Type typeFromHandle = typeof(StringExtensionMethods);
			_getStableHashCodeStringBool = typeFromHandle.GetMethod("GetStableHashCode", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2]
			{
				typeof(string),
				typeof(bool)
			}, null);
			_getStableHashCodeString = typeFromHandle.GetMethod("GetStableHashCode", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
			_initialized = true;
		}
		catch
		{
			_initialized = false;
		}
	}

	public static int StableHash(string value)
	{
		if (value == null)
		{
			return 0;
		}
		try
		{
			if (_getStableHashCodeStringBool != null)
			{
				return (int)_getStableHashCodeStringBool.Invoke(null, new object[2] { value, false });
			}
			if (_getStableHashCodeString != null)
			{
				return (int)_getStableHashCodeString.Invoke(null, new object[1] { value });
			}
		}
		catch
		{
		}
		return FallbackStableHash(value);
	}

	private static int FallbackStableHash(string value)
	{
		int num = 5381;
		int num2 = num;
		for (int i = 0; i < value.Length; i += 2)
		{
			num = ((num << 5) + num) ^ value[i];
			if (i == value.Length - 1)
			{
				break;
			}
			num2 = ((num2 << 5) + num2) ^ value[i + 1];
		}
		return num + num2 * 1566083941;
	}
}
public class FishProcreation : MonoBehaviour
{
	private static readonly int ZdoNextBreedKey = StringExtensionMethods.GetStableHashCode("Balrond_FishNextBreed");

	private static readonly int ZdoBornKey = StringExtensionMethods.GetStableHashCode("Balrond_FishBorn");

	public float m_updateInterval = 120f;

	public float m_partnerRange = 8f;

	public float m_totalCheckRange = 16f;

	public int m_maxFishNearby = 8;

	public float m_spawnChance = 0.2f;

	public float m_breedCooldown = 450f;

	public float m_childMaturityTime = 900f;

	public float m_spawnOffset = 2f;

	private ZNetView m_nview;

	private Fish m_fish;

	private GameObject m_myPrefab;

	private void Awake()
	{
		m_nview = ((Component)this).GetComponent<ZNetView>();
		m_fish = ((Component)this).GetComponent<Fish>();
		if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.GetZDO() != null)
		{
			ZDO zDO = m_nview.GetZDO();
			if (zDO.GetLong(ZdoBornKey, 0L) == 0)
			{
				zDO.Set(ZdoBornKey, GetTime().Ticks);
			}
			if (zDO.GetLong(ZdoNextBreedKey, 0L) == 0)
			{
				SetNextBreed(Random.Range(m_childMaturityTime * 0.5f, m_childMaturityTime));
			}
		}
		((MonoBehaviour)this).InvokeRepeating("TryProcreate", Random.Range(m_updateInterval, m_updateInterval * 1.5f), m_updateInterval);
	}

	private void TryProcreate()
	{
		if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid() && m_nview.IsOwner() && !((Object)(object)m_fish == (Object)null) && !m_fish.IsOutOfWater() && IsMature() && BreedCooldownReady() && !(Random.value > m_spawnChance))
		{
			if ((Object)(object)m_myPrefab == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				m_myPrefab = ZNetScene.instance.GetPrefab(m_nview.GetZDO().GetPrefab());
			}
			if (!((Object)(object)m_myPrefab == (Object)null) && !TooManyNearby() && HasPartner())
			{
				SpawnBabyFish();
				SetNextBreed(m_breedCooldown);
			}
		}
	}

	private bool HasPartner()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		int nrOfInstances = SpawnSystem.GetNrOfInstances(m_myPrefab, ((Component)this).transform.position, m_partnerRange, false, true);
		return nrOfInstances >= 2;
	}

	private bool TooManyNearby()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		int nrOfInstances = SpawnSystem.GetNrOfInstances(m_myPrefab, ((Component)this).transform.position, m_totalCheckRange, false, false);
		return nrOfInstances >= m_maxFishNearby;
	}

	private bool IsMature()
	{
		ZDO zdo = GetZdo();
		if (zdo == null)
		{
			return false;
		}
		long num = zdo.GetLong(ZdoBornKey, 0L);
		if (num <= 0)
		{
			return true;
		}
		return (GetTime() - new DateTime(num)).TotalSeconds >= (double)m_childMaturityTime;
	}

	private bool BreedCooldownReady()
	{
		ZDO zdo = GetZdo();
		if (zdo == null)
		{
			return false;
		}
		long num = zdo.GetLong(ZdoNextBreedKey, 0L);
		if (num <= 0)
		{
			return true;
		}
		return GetTime() >= new DateTime(num);
	}

	private void SetNextBreed(float secondsFromNow)
	{
		ZDO zdo = GetZdo();
		if (zdo != null)
		{
			zdo.Set(ZdoNextBreedKey, GetTime().AddSeconds(secondsFromNow).Ticks);
		}
	}

	private void SpawnBabyFish()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: 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)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: 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_0041: 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_0062: Unknown result type (might be due to invalid IL or missing references)
		Vector2 insideUnitCircle = Random.insideUnitCircle;
		Vector2 val = ((Vector2)(ref insideUnitCircle)).normalized * m_spawnOffset;
		Vector3 val2 = ((Component)this).transform.position + new Vector3(val.x, 0f, val.y);
		GameObject val3 = Object.Instantiate<GameObject>(m_myPrefab, val2, Quaternion.Euler(0f, Random.Range(0f, 360f), 0f));
		ItemDrop component = ((Component)this).GetComponent<ItemDrop>();
		ItemDrop component2 = val3.GetComponent<ItemDrop>();
		if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null)
		{
			component2.SetQuality(component.m_itemData.m_quality);
		}
		ZNetView component3 = val3.GetComponent<ZNetView>();
		if ((Object)(object)component3 != (Object)null && component3.IsValid() && component3.GetZDO() != null)
		{
			ZDO zDO = component3.GetZDO();
			zDO.Set(ZdoBornKey, GetTime().Ticks);
			zDO.Set(ZdoNextBreedKey, GetTime().AddSeconds(m_childMaturityTime).Ticks);
		}
	}

	private ZDO GetZdo()
	{
		if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
		{
			return null;
		}
		return m_nview.GetZDO();
	}

	private DateTime GetTime()
	{
		return ((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTime() : DateTime.Now;
	}
}
public static class CreatureFactionRegistry
{
	public enum Mode
	{
		Static,
		DynamicBiome
	}

	public enum TimeCondition
	{
		Any,
		Day,
		Night
	}

	public sealed class BiomeTimeFactionRule
	{
		public Biome Biome;

		public TimeCondition Time;

		public string FactionName;

		public BiomeTimeFactionRule(Biome biome, TimeCondition time, string factionName)
		{
			//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)
			Biome = biome;
			Time = time;
			FactionName = factionName;
		}
	}

	public sealed class CreatureFactionRule
	{
		public string PrefabName;

		public string DefaultFactionName;

		public Mode Mode = Mode.Static;

		public Dictionary<Biome, string> BiomeFactions = new Dictionary<Biome, string>();

		public List<BiomeTimeFactionRule> BiomeTimeFactions = new List<BiomeTimeFactionRule>();
	}

	private static readonly Dictionary<string, CreatureFactionRule> Rules = new Dictionary<string, CreatureFactionRule>(StringComparer.OrdinalIgnoreCase);

	private static readonly Dictionary<Biome, string> DefaultBiomeFactions = new Dictionary<Biome, string>();

	public static void RegisterCreature(CreatureFactionRule rule)
	{
		if (rule != null && !string.IsNullOrEmpty(rule.PrefabName))
		{
			Rules[rule.PrefabName] = rule;
		}
	}

	public static void SetBiomeFaction(Biome biome, string factionName)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		DefaultBiomeFactions[biome] = factionName;
	}

	public static void RegisterDefaultBiomeFactionMap()
	{
		SetBiomeFaction((Biome)1, "AnimalsVeg");
		SetBiomeFaction((Biome)8, "ForestMonsters");
		SetBiomeFaction((Biome)2, "Undead");
		SetBiomeFaction((Biome)4, "MountainMonsters");
		SetBiomeFaction((Biome)16, "PlainsMonsters");
		SetBiomeFaction((Biome)256, "SeaMonsters");
		SetBiomeFaction((Biome)512, "MistlandsMonsters");
		SetBiomeFaction((Biome)32, "Demon");
		SetBiomeFaction((Biome)64, "MountainMonsters");
	}

	public static void InitExampleRegistry()
	{
		RegisterDefaultBiomeFactionMap();
	}

	public static void Apply(Character character)
	{
		//IL_005a: 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)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)character == (Object)null)
		{
			return;
		}
		string prefabName = GetPrefabName(((Component)character).gameObject);
		if (!Rules.TryGetValue(prefabName, out var value))
		{
			return;
		}
		string text = value.DefaultFactionName;
		if (value.Mode == Mode.DynamicBiome)
		{
			Biome biome = GetBiome(((Component)character).transform.position);
			BiomeTimeFactionRule biomeTimeFactionRule = FindBiomeTimeRule(value, biome);
			if (biomeTimeFactionRule != null)
			{
				text = biomeTimeFactionRule.FactionName;
			}
			else if (value.BiomeFactions.ContainsKey(biome))
			{
				text = value.BiomeFactions[biome];
			}
			else if (string.IsNullOrEmpty(text) && DefaultBiomeFactions.ContainsKey(biome))
			{
				text = DefaultBiomeFactions[biome];
			}
		}
		if (!string.IsNullOrEmpty(text) && CustomFactionRegistry.TryGetFaction(text, out var faction))
		{
			character.m_faction = (Faction)faction.ID;
		}
	}

	private static BiomeTimeFactionRule FindBiomeTimeRule(CreatureFactionRule rule, Biome biome)
	{
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		if (rule.BiomeTimeFactions == null || rule.BiomeTimeFactions.Count == 0)
		{
			return null;
		}
		TimeCondition timeCondition = ((!IsNight()) ? TimeCondition.Day : TimeCondition.Night);
		BiomeTimeFactionRule result = null;
		for (int i = 0; i < rule.BiomeTimeFactions.Count; i++)
		{
			BiomeTimeFactionRule biomeTimeFactionRule = rule.BiomeTimeFactions[i];
			if (biomeTimeFactionRule != null && biomeTimeFactionRule.Biome == biome)
			{
				if (biomeTimeFactionRule.Time == timeCondition)
				{
					return biomeTimeFactionRule;
				}
				if (biomeTimeFactionRule.Time == TimeCondition.Any)
				{
					result = biomeTimeFactionRule;
				}
			}
		}
		return result;
	}

	private static bool IsNight()
	{
		return (Object)(object)EnvMan.instance != (Object)null && EnvMan.instance.CalculateNight();
	}

	private static Biome GetBiome(Vector3 position)
	{
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: 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_0018: 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_0035: Unknown result type (might be due to invalid IL or missing references)
		if (WorldGenerator.instance != null)
		{
			return WorldGenerator.instance.GetBiome(position.x, position.z, 0.02f, false);
		}
		return Heightmap.FindBiome(position);
	}

	private static string GetPrefabName(GameObject go)
	{
		string text = ((Object)go).name;
		int num = text.IndexOf("(Clone)", StringComparison.Ordinal);
		if (num >= 0)
		{
			text = text.Substring(0, num);
		}
		return text;
	}
}
[HarmonyPatch(typeof(Character), "Awake")]
public static class Character_Awake_CreatureFactionPatch
{
	private static void Postfix(Character __instance)
	{
		CreatureFactionRegistry.Apply(__instance);
	}
}
public static class CustomFactionRegistry
{
	public sealed class FactionDefinition
	{
		public int ID;

		public string Name;

		public List<FactionRelation> Relations = new List<FactionRelation>();
	}

	public sealed class FactionRelation
	{
		public string Name;

		public bool Enemy;

		public FactionRelation(string name, bool enemy)
		{
			Name = name;
			Enemy = enemy;
		}
	}

	private static readonly Dictionary<string, FactionDefinition> ByName = new Dictionary<string, FactionDefinition>(StringComparer.OrdinalIgnoreCase);

	private static readonly Dictionary<int, FactionDefinition> ById = new Dictionary<int, FactionDefinition>();

	private static readonly Dictionary<string, bool> Relations = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);

	private static bool _vanillaRegistered;

	public static void InitExampleRegistry()
	{
		Init();
	}

	public static void Init()
	{
		RegisterVanillaFactions();
	}

	public static void RegisterFaction(FactionDefinition faction)
	{
		Init();
		ByName[faction.Name] = faction;
		ById[faction.ID] = faction;
		SetRelation(faction.Name, faction.Name, enemy: false);
		foreach (FactionRelation relation in faction.Relations)
		{
			SetRelation(faction.Name, relation.Name, relation.Enemy);
		}
	}

	public static void SetRelation(string factionA, string factionB, bool enemy)
	{
		Relations[Key(factionA, factionB)] = enemy;
		Relations[Key(factionB, factionA)] = enemy;
	}

	public static bool TryGetFaction(string name, out FactionDefinition faction)
	{
		Init();
		return ByName.TryGetValue(name, out faction);
	}

	public static Faction GetFaction(string name)
	{
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		Init();
		if (!ByName.TryGetValue(name, out var value))
		{
			throw new Exception("Unknown faction: " + name);
		}
		return (Faction)value.ID;
	}

	public static string GetFactionName(Faction faction)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Expected I4, but got Unknown
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected I4, but got Unknown
		Init();
		if (ById.TryGetValue((int)faction, out var value))
		{
			return value.Name;
		}
		return ((int)faction).ToString();
	}

	public static bool IsRegistered(Faction faction)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Expected I4, but got Unknown
		Init();
		return ById.ContainsKey((int)faction);
	}

	public static bool AreEnemies(Character a, Character b)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)a == (Object)null || (Object)(object)b == (Object)null)
		{
			return false;
		}
		if ((Object)(object)a == (Object)(object)b)
		{
			return false;
		}
		string factionName = GetFactionName(a.m_faction);
		string factionName2 = GetFactionName(b.m_faction);
		if (Relations.TryGetValue(Key(factionName, factionName2), out var value))
		{
			return value;
		}
		bool flag = IsCustomFaction(a.m_faction);
		bool flag2 = IsCustomFaction(b.m_faction);
		if (!flag && !flag2)
		{
			return false;
		}
		return factionName != factionName2;
	}

	public static bool HasExplicitRelation(Character a, Character b)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		string factionName = GetFactionName(a.m_faction);
		string factionName2 = GetFactionName(b.m_faction);
		return Relations.ContainsKey(Key(factionName, factionName2));
	}

	public static bool IsCustomFaction(Faction faction)
	{
		//IL_0007: 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_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		Init();
		string factionName = GetFactionName(faction);
		try
		{
			Faction val = (Faction)Enum.Parse(typeof(Faction), factionName);
			return val != faction;
		}
		catch
		{
			return true;
		}
	}

	private unsafe static void RegisterVanillaFactions()
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Expected I4, but got Unknown
		if (_vanillaRegistered)
		{
			return;
		}
		_vanillaRegistered = true;
		Array values = Enum.GetValues(typeof(Faction));
		foreach (object item in values)
		{
			Faction val = (Faction)item;
			FactionDefinition factionDefinition = new FactionDefinition
			{
				ID = (int)val,
				Name = ((object)(*(Faction*)(&val))/*cast due to .constrained prefix*/).ToString()
			};
			ByName[factionDefinition.Name] = factionDefinition;
			ById[factionDefinition.ID] = factionDefinition;
		}
	}

	private static string Key(string a, string b)
	{
		return a + "->" + b;
	}
}
[HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[]
{
	typeof(Character),
	typeof(Character)
})]
public static class BaseAI_IsEnemy_CustomFactionPatch
{
	private static bool Prefix(Character a, Character b, ref bool __result)
	{
		//IL_001d: 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)
		if ((Object)(object)a == (Object)null || (Object)(object)b == (Object)null)
		{
			return true;
		}
		bool flag = CustomFactionRegistry.IsCustomFaction(a.m_faction) || CustomFactionRegistry.IsCustomFaction(b.m_faction);
		bool flag2 = CustomFactionRegistry.HasExplicitRelation(a, b);
		if (!flag && !flag2)
		{
			return true;
		}
		__result = CustomFactionRegistry.AreEnemies(a, b);
		return false;
	}
}
namespace UpgradeWorld
{
	public class CommandRegistration
	{
		public string name = "";

		public string description = "";

		public string[] commands = new string[0];

		public void AddCommand()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			new ConsoleCommand(name, description, (ConsoleEvent)delegate(ConsoleEventArgs args)
			{
				string[] array = commands;
				foreach (string text in array)
				{
					args.Context.TryRunCommand(text, false, false);
				}
			}, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
	}
	[HarmonyPatch(typeof(Terminal), "InitTerminal")]
	public static class Upgrade
	{
		private static List<CommandRegistration> registrations = new List<CommandRegistration>();

		public const string GUID = "upgrade_world";

		public static void Register(string name, string description, params string[] commands)
		{
			if (Chainloader.PluginInfos.ContainsKey("upgrade_world"))
			{
				registrations.Add(new CommandRegistration
				{
					name = name,
					description = description,
					commands = commands
				});
			}
		}

		private static void Postfix()
		{
			foreach (CommandRegistration registration in registrations)
			{
				registration.AddCommand();
			}
		}
	}
}
namespace BalrondNature
{
	public class TableMapper
	{
		public static CraftingStation cauldron;

		public static CraftingStation workbench;

		public static CraftingStation heavyWorkbench;

		public static CraftingStation forge;

		public static CraftingStation ironworks;

		public static CraftingStation blackforge;

		public static CraftingStation stoneCutter;

		public static CraftingStation artisian;

		public static CraftingStation magetable;

		public static CraftingStation runeforge;

		public static CraftingStation tannery;

		public static CraftingStation fletcher;

		public static CraftingStation grill;

		public static CraftingStation alchemylab;

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

		public static void setupTables(List<GameObject> list)
		{
			pieces = list;
			prepareTables();
		}

		private static CraftingStation FindStation(List<GameObject> list, string name)
		{
			GameObject val = list.Find((GameObject x) => ((Object)x).name == name);
			if ((Object)(object)val != (Object)null)
			{
				return val.GetComponent<CraftingStation>();
			}
			Debug.LogWarning((object)("TableMapper - Station not found: " + name));
			return null;
		}

		private static void prepareTables()
		{
			cauldron = FindStation(pieces, "piece_cauldron");
			workbench = FindStation(pieces, "piece_workbench");
			heavyWorkbench = FindStation(pieces, "piece_heavy_workbench_bal");
			forge = FindStation(pieces, "forge");
			ironworks = FindStation(pieces, "piece_metalworks_bal");
			blackforge = FindStation(pieces, "blackforge");
			stoneCutter = FindStation(pieces, "piece_stonecutter");
			artisian = FindStation(pieces, "piece_artisanstation");
			runeforge = FindStation(pieces, "piece_runeforge_bal");
			magetable = FindStation(pieces, "piece_magetable");
			fletcher = FindStation(pieces, "piece_fletcher_bal");
		}
	}
}
namespace BalrondExtendedAnimals
{
	public class BalrondTranslator
	{
		public static Dictionary<string, Dictionary<string, string>> translations = new Dictionary<string, Dictionary<string, string>>();

		public static Dictionary<string, string> getLanguage(string language)
		{
			Dictionary<string, string> result = null;
			try
			{
				result = translations[language];
			}
			catch (Exception)
			{
			}
			return result;
		}
	}
	[DisallowMultipleComponent]
	public class AnimalAITamable : MonoBehaviour, Interactable, TextReceiver
	{
		private const float m_playerMaxDistance = 15f;

		private const float m_tameDeltaTime = 3f;

		private static readonly List<Player> s_nearbyPlayers = new List<Player>();

		private static int s_itemMask;

		[Header("Tameable")]
		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 float m_tamingSpeedMultiplierRange = 60f;

		public float m_tamingBoostMultiplier = 2f;

		public bool m_nameBeforeText = true;

		public string m_tameText = "$hud_tamelove";

		private const string RPC_SetNameKey = "BalrondExtendedAnimals_SetName";

		private bool m_rpcRegistered;

		[Header("Balrond rules")]
		public bool m_canBeTamed = true;

		public bool m_canProcreateWild = true;

		public bool m_canProcreateTamed = true;

		[Header("Consume items")]
		public List<ItemDrop> m_consumeItems = new List<ItemDrop>();

		public float m_consumeRange = 2f;

		public float m_consumeSearchRange = 5f;

		public float m_consumeSearchInterval = 10f;

		public EffectList m_consumeItemEffects = new EffectList();

		public Action<ItemDrop> m_onConsumedItem;

		[Header("Procreation")]
		public bool m_enableProcreation = true;

		public float m_updateInterval = 10f;

		public float m_totalCheckRange = 10f;

		public int m_maxCreatures = 4;

		public float m_partnerCheckRange = 3f;

		public float m_pregnancyChance = 0.5f;

		public float m_pregnancyDuration = 10f;

		public int m_requiredLovePoints = 4;

		public GameObject m_offspring;

		public int m_minOffspringLevel;

		public float m_spawnOffset = 2f;

		public float m_spawnOffsetMax;

		public bool m_spawnRandomDirection;

		public GameObject m_seperatePartner;

		public GameObject m_noPartnerOffspring;

		public EffectList m_birthEffects = new EffectList();

		public EffectList m_loveEffects = new EffectList();

		[Header("AnimalAI bridge")]
		public bool m_disableFleeWhenTamed = true;

		public bool m_clearTargetWhenTamed = true;

		public bool m_clearAlertedWhenTamed = true;

		public bool m_disableAfraidOfFireWhenTamed;

		[Header("Naming")]
		public bool m_allowRename = true;

		public int m_maxNameLength = 10;

		private ZNetView m_nview;

		private Character m_character;

		private BaseAI m_baseAI;

		private AnimalAI m_animalAI;

		private Piece m_piece;

		private ItemDrop m_consumeTarget;

		private float m_consumeSearchTimer;

		private float m_lastPetTime;

		private GameObject m_myPrefab;

		private GameObject m_offspringPrefab;

		private static readonly BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly FieldInfo FI_AnimalAI_Target = typeof(AnimalAI).GetField("m_target", Flags);

		private static readonly FieldInfo FI_AnimalAI_InDangerTimer = typeof(AnimalAI).GetField("m_inDangerTimer", Flags);

		private static readonly FieldInfo FI_BaseAI_AfraidOfFire = typeof(BaseAI).GetField("m_afraidOfFire", Flags);

		private static readonly FieldInfo FI_BaseAI_AvoidFire = typeof(BaseAI).GetField("m_avoidFire", Flags);

		private static readonly MethodInfo MI_BaseAI_SetAlerted = typeof(BaseAI).GetMethod("SetAlerted", Flags);

		public static AnimalAITamable AddTo(GameObject go)
		{
			AnimalAITamable component = go.GetComponent<AnimalAITamable>();
			return Object.op_Implicit((Object)(object)component) ? component : go.AddComponent<AnimalAITamable>();
		}

		private void Awake()
		{
			AnimalAITamable[] components = ((Component)this).GetComponents<AnimalAITamable>();
			if (components.Length > 1 && (Object)(object)components[0] != (Object)(object)this)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			CacheComponents();
			if (Object.op_Implicit((Object)(object)m_character))
			{
				Character character = m_character;
				character.m_onDeath = (Action)Delegate.Combine(character.m_onDeath, new Action(OnDeath));
			}
			if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
			{
				if (!m_rpcRegistered)
				{
					m_rpcRegistered = true;
					m_nview.Register<string>("BalrondExtendedAnimals_SetName", (Action<long, string>)RPC_SetName);
				}
				((MonoBehaviour)this).CancelInvoke("TamingUpdate");
				if (m_canBeTamed)
				{
					((MonoBehaviour)this).InvokeRepeating("TamingUpdate", 3f, 3f);
				}
				((MonoBehaviour)this).CancelInvoke("Procreate");
				if (m_enableProcreation && m_canProcreateTamed)
				{
					((MonoBehaviour)this).InvokeRepeating("Procreate", Random.Range(m_updateInterval, m_updateInterval + m_updateInterval * 0.5f), m_updateInterval);
				}
			}
			if (m_startsTamed && Object.op_Implicit((Object)(object)m_character))
			{
				m_character.SetTamed(true);
				OnBecomeTamed();
			}
		}

		private void Update()
		{
			EnsureComponents();
			if (m_disableFleeWhenTamed && IsTamed())
			{
				ApplyTamedAnimalAIState();
			}
			UpdateConsume(Time.deltaTime);
		}

		public void CacheComponents()
		{
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_character = ((Component)this).GetComponent<Character>();
			m_baseAI = ((Component)this).GetComponent<BaseAI>();
			m_animalAI = ((Component)this).GetComponent<AnimalAI>();
			m_piece = ((Component)this).GetComponent<Piece>();
		}

		private void EnsureComponents()
		{
			if (!Object.op_Implicit((Object)(object)m_nview))
			{
				m_nview = ((Component)this).GetComponent<ZNetView>();
			}
			if (!Object.op_Implicit((Object)(object)m_character))
			{
				m_character = ((Component)this).GetComponent<Character>();
			}
			if (!Object.op_Implicit((Object)(object)m_baseAI))
			{
				m_baseAI = ((Component)this).GetComponent<BaseAI>();
			}
			if (!Object.op_Implicit((Object)(object)m_animalAI))
			{
				m_animalAI = ((Component)this).GetComponent<AnimalAI>();
			}
			if (!Object.op_Implicit((Object)(object)m_piece))
			{
				m_piece = ((Component)this).GetComponent<Piece>();
			}
		}

		public bool IsTamed()
		{
			EnsureComponents();
			return (Object.op_Implicit((Object)(object)m_character) && m_character.IsTamed()) || m_startsTamed;
		}

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

		public string GetName()
		{
			EnsureComponents();
			string text = (Object.op_Implicit((Object)(object)m_character) ? m_character.m_name : (Object.op_Implicit((Object)(object)m_piece) ? m_piece.m_name : ((Object)((Component)this).gameObject).name));
			if (Object.op_Implicit((Object)(object)m_nview) && m_nview.IsValid())
			{
				string text2 = m_nview.GetZDO().GetString(ZDOVars.s_tamedName, "");
				if (!string.IsNullOrEmpty(text2))
				{
					return text2;
				}
			}
			return Localization.instance.Localize(text);
		}

		public string GetHoverName()
		{
			string text = GetText();
			return (!string.IsNullOrEmpty(text)) ? StringExtensionMethods.RemoveRichTextTags(text) : GetName();
		}

		public string GetStatusString()
		{
			EnsureComponents();
			if (Object.op_Implicit((Object)(object)m_baseAI) && m_baseAI.IsAlerted())
			{
				return "$hud_tamefrightened";
			}
			if (IsHungry())
			{
				return "$hud_tamehungry";
			}
			return IsTamed() ? "$hud_tamehappy" : "$hud_tameinprogress";
		}

		public string GetHoverText()
		{
			EnsureComponents();
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid())
			{
				return "";
			}
			string name = GetName();
			if (IsTamed())
			{
				name += Localization.instance.Localize(" ( $hud_tame, " + GetStatusString() + " )");
				string text = name + Localization.instance.Localize("\n[<color=yellow><b>$KEY_Use</b></color>] $hud_pet");
				if (m_allowRename)
				{
					text += ((!ZInput.IsNonClassicFunctionality() || !ZInput.IsGamepadActive()) ? Localization.instance.Localize("\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] $hud_rename") : Localization.instance.Localize("\n[<color=yellow><b>$KEY_AltKeys + $KEY_Use</b></color>] $hud_rename"));
				}
				return text;
			}
			if (!m_canBeTamed)
			{
				return name + Localization.instance.Localize(" ( $hud_wild )");
			}
			int tameness = GetTameness();
			return (tameness <= 0) ? (name + Localization.instance.Localize(" ( $hud_wild, " + GetStatusString() + " )")) : (name + Localization.instance.Localize(" ( $hud_tameness  " + tameness + "%, " + GetStatusString() + " )"));
		}

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			EnsureComponents();
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid() || hold)
			{
				return false;
			}
			if (alt && m_allowRename)
			{
				RequestRename();
				return true;
			}
			if (!IsTamed() || Time.time - m_lastPetTime <= 1f)
			{
				return false;
			}
			m_lastPetTime = Time.time;
			m_petEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1);
			string text = (m_nameBeforeText ? (GetHoverName() + " " + m_tameText) : m_tameText);
			((Character)user).Message((MessageType)2, text, 0, (Sprite)null);
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			EnsureComponents();
			if (!m_canBeTamed)
			{
				return false;
			}
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid() || item == null)
			{
				return false;
			}
			if (!CanConsume(item))
			{
				return false;
			}
			if (!IsHungry())
			{
				((Character)user).Message((MessageType)2, GetHoverName() + " $hud_tamehappy", 0, (Sprite)null);
				return true;
			}
			if (Object.op_Implicit((Object)(object)m_baseAI) && m_baseAI.IsAlerted())
			{
				((Character)user).Message((MessageType)2, GetHoverName() + " $hud_tamefrightened", 0, (Sprite)null);
				return true;
			}
			if (Vector3.Distance(((Component)user).transform.position, ((Component)this).transform.position) > 15f)
			{
				return false;
			}
			if (!user.GetInventory().RemoveOneItem(item))
			{
				return false;
			}
			ItemDrop item2 = (Object.op_Implicit((Object)(object)item.m_dropPrefab) ? item.m_dropPrefab.GetComponent<ItemDrop>() : null);
			OnConsumedItem(item2);
			return true;
		}

		private void RequestRename()
		{
			if (IsTamed() && (Object)(object)TextInput.instance != (Object)null)
			{
				TextInput.instance.RequestText((TextReceiver)(object)this, "$hud_rename", m_maxNameLength);
			}
		}

		public string GetText()
		{
			EnsureComponents();
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid())
			{
				return "";
			}
			return m_nview.GetZDO().GetString(ZDOVars.s_tamedName, "");
		}

		public void SetText(string text)
		{
			EnsureComponents();
			if (Object.op_Implicit((Object)(object)m_nview) && m_nview.IsValid())
			{
				if (text == null)
				{
					text = "";
				}
				text = text.Trim();
				if (text.Length > m_maxNameLength)
				{
					text = text.Substring(0, m_maxNameLength);
				}
				m_nview.InvokeRPC("BalrondExtendedAnimals_SetName", new object[1] { text });
			}
		}

		private void RPC_SetName(long sender, string name)
		{
			EnsureComponents();
			if (Object.op_Implicit((Object)(object)m_nview) && m_nview.IsValid() && m_nview.IsOwner() && IsTamed())
			{
				if (name == null)
				{
					name = "";
				}
				name = name.Trim();
				if (name.Length > m_maxNameLength)
				{
					name = name.Substring(0, m_maxNameLength);
				}
				m_nview.GetZDO().Set(ZDOVars.s_tamedName, name);
			}
		}

		private void TamingUpdate()
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			EnsureComponents();
			if (m_canBeTamed && Object.op_Implicit((Object)(object)m_nview) && m_nview.IsValid() && m_nview.IsOwner() && !IsTamed() && !IsHungry() && (!Object.op_Implicit((Object)(object)m_baseAI) || !m_baseAI.IsAlerted()))
			{
				DecreaseRemainingTime(3f);
				if (GetRemainingTime() <= 0f)
				{
					Tame();
				}
				else
				{
					m_sootheEffect.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1);
				}
			}
		}

		private void Tame()
		{
			//IL_009e: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			EnsureComponents();
			if (!m_canBeTamed)
			{
				return;
			}
			if ((Object)(object)Game.instance != (Object)null)
			{
				Game.instance.IncrementPlayerStat((PlayerStatType)48, 1f);
			}
			if (Object.op_Implicit((Object)(object)m_nview) && m_nview.IsValid() && m_nview.IsOwner() && Object.op_Implicit((Object)(object)m_character) && !IsTamed())
			{
				m_character.SetTamed(true);
				OnBecomeTamed();
				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);
				}
			}
		}

		private void OnBecomeTamed()
		{
			EnsureComponents();
			if (Object.op_Implicit((Object)(object)m_baseAI))
			{
				ForceSetAlerted(alert: false);
				ClearAnimalTarget();
				if (m_disableAfraidOfFireWhenTamed)
				{
					TrySetField(FI_BaseAI_AfraidOfFire, m_baseAI, false);
					TrySetField(FI_BaseAI_AvoidFire, m_baseAI, false);
				}
			}
		}

		private void ApplyTamedAnimalAIState()
		{
			EnsureComponents();
			if (Object.op_Implicit((Object)(object)m_animalAI))
			{
				if (m_clearTargetWhenTamed)
				{
					ClearAnimalTarget();
					TrySetField(FI_AnimalAI_InDangerTimer, m_animalAI, m_animalAI.m_timeToSafe + 0.1f);
				}
				if (m_clearAlertedWhenTamed)
				{
					ForceSetAlerted(alert: false);
				}
			}
		}

		private void ClearAnimalTarget()
		{
			if (FI_AnimalAI_Target != null && Object.op_Implicit((Object)(object)m_animalAI))
			{
				FI_AnimalAI_Target.SetValue(m_animalAI, null);
			}
		}

		private void ForceSetAlerted(bool alert)
		{
			if (MI_BaseAI_SetAlerted != null && Object.op_Implicit((Object)(object)m_baseAI))
			{
				MI_BaseAI_SetAlerted.Invoke(m_baseAI, new object[1] { alert });
			}
		}

		private static void TrySetField(FieldInfo field, object instance, object value)
		{
			if (field != null && instance != null)
			{
				field.SetValue(instance, value);
			}
		}

		private void OnDeath()
		{
		}

		private int GetTameness()
		{
			return (int)((1f - Mathf.Clamp01(GetRemainingTime() / m_tamingTime)) * 100f);
		}

		private void ResetFeedingTimer()
		{
			EnsureComponents();
			if (Object.op_Implicit((Object)(object)m_nview) && m_nview.IsValid())
			{
				m_nview.GetZDO().Set(ZDOVars.s_tameLastFeeding, ZNet.instance.GetTime().Ticks);
			}
		}

		private void DecreaseRemainingTime(float time)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			EnsureComponents();
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid())
			{
				return;
			}
			float remainingTime = GetRemainingTime();
			s_nearbyPlayers.Clear();
			Player.GetPlayersInRange(((Component)this).transform.position, m_tamingSpeedMultiplierRange, s_nearbyPlayers);
			foreach (Player s_nearbyPlayer in s_nearbyPlayers)
			{
				if (((Character)s_nearbyPlayer).GetSEMan().HaveStatusAttribute((StatusAttribute)8))
				{
					time *= m_tamingBoostMultiplier;
				}
			}
			float num = remainingTime - time;
			if (num < 0f)
			{
				num = 0f;
			}
			m_nview.GetZDO().Set(ZDOVars.s_tameTimeLeft, num);
		}

		private float GetRemainingTime()
		{
			EnsureComponents();
			return (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid()) ? 0f : m_nview.GetZDO().GetFloat(ZDOVars.s_tameTimeLeft, m_tamingTime);
		}

		private void OnConsumedItem(ItemDrop item)
		{
			//IL_002c: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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)
			if (IsHungry())
			{
				Vector3 val = (Object.op_Implicit((Object)(object)m_character) ? m_character.GetCenterPoint() : ((Component)this).transform.position);
				m_sootheEffect.Create(val, Quaternion.identity, (Transform)null, 1f, -1);
			}
			ResetFeedingTimer();
			m_onConsumedItem?.Invoke(item);
			m_consumeItemEffects.Create(((Component)this).transform.position, Quaternion.identity, (Transform)null, 1f, -1);
			if ((Object)(object)m_character != (Object)null && (Object)(object)m_character.m_zanim != (Object)null)
			{
				m_character.m_zanim.SetTrigger("consume");
			}
		}

		public bool CanConsume(ItemData item)
		{
			if (item == null || m_consumeItems == null)
			{
				return false;
			}
			foreach (ItemDrop consumeItem in m_consumeItems)
			{
				if (Object.op_Implicit((Object)(object)consumeItem) && consumeItem.m_itemData.m_shared.m_name == item.m_shared.m_name)
				{
					return true;
				}
			}
			return false;
		}

		private void UpdateConsume(float dt)
		{
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			EnsureComponents();
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid() || !m_nview.IsOwner() || m_consumeItems == null || m_consumeItems.Count == 0 || !IsHungry() || (Object.op_Implicit((Object)(object)m_baseAI) && m_baseAI.IsAlerted()))
			{
				return;
			}
			m_consumeSearchTimer += dt;
			if (m_consumeSearchTimer > m_consumeSearchInterval)
			{
				m_consumeSearchTimer = 0f;
				m_consumeTarget = FindClosestConsumableItem(m_consumeSearchRange);
			}
			if (Object.op_Implicit((Object)(object)m_consumeTarget) && Object.op_Implicit((Object)(object)m_baseAI) && m_baseAI.MoveTo(dt, ((Component)m_consumeTarget).transform.position, m_consumeRange, false))
			{
				m_baseAI.LookAt(((Component)m_consumeTarget).transform.position);
				if (m_baseAI.IsLookingAt(((Component)m_consumeTarget).transform.position, 20f, false) && m_consumeTarget.RemoveOne())
				{
					OnConsumedItem(m_consumeTarget);
					m_consumeTarget = null;
				}
			}
		}

		private ItemDrop FindClosestConsumableItem(float maxRange)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			EnsureComponents();
			if (s_itemMask == 0)
			{
				s_itemMask = LayerMask.GetMask(new string[1] { "item" });
			}
			Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, maxRange, s_itemMask);
			ItemDrop val = null;
			float num = 999999f;
			Collider[] array2 = array;
			foreach (Collider val2 in array2)
			{
				if (!Object.op_Implicit((Object)(object)val2.attachedRigidbody))
				{
					continue;
				}
				ItemDrop component = ((Component)val2.attachedRigidbody).GetComponent<ItemDrop>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					continue;
				}
				ZNetView component2 = ((Component)component).GetComponent<ZNetView>();
				if (Object.op_Implicit((Object)(object)component2) && component2.IsValid() && CanConsume(component.m_itemData))
				{
					float num2 = Vector3.Distance(((Component)component).transform.position, ((Component)this).transform.position);
					if (!Object.op_Implicit((Object)(object)val) || num2 < num)
					{
						val = component;
						num = num2;
					}
				}
			}
			return (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)m_baseAI) && m_baseAI.HavePath(((Component)val).transform.position)) ? val : null;
		}

		private void Procreate()
		{
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			EnsureComponents();
			if (!m_enableProcreation || !m_canProcreateTamed || !Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid() || !m_nview.IsOwner() || m_nview.GetZDO() == null || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || !IsTamed() || (Object)(object)m_offspring == (Object)null)
			{
				return;
			}
			if ((Object)(object)m_offspringPrefab == (Object)null)
			{
				m_offspringPrefab = ZNetScene.instance.GetPrefab(Utils.GetPrefabName(m_offspring));
				m_myPrefab = ZNetScene.instance.GetPrefab(m_nview.GetZDO().GetPrefab());
			}
			if ((Object)(object)m_offspringPrefab == (Object)null || (Object)(object)m_myPrefab == (Object)null)
			{
				return;
			}
			if (IsPregnant())
			{
				if (IsDue())
				{
					ResetPregnancy();
					SpawnOffspring(parentIsTamed: true);
				}
			}
			else
			{
				if ((Object.op_Implicit((Object)(object)m_baseAI) && m_baseAI.IsAlerted()) || IsHungry() || Random.value > m_pregnancyChance)
				{
					return;
				}
				int num = SpawnSystem.GetNrOfInstances(m_myPrefab, ((Component)this).transform.position, m_totalCheckRange, false, false) + SpawnSystem.GetNrOfInstances(m_offspringPrefab, ((Component)this).transform.position, m_totalCheckRange, false, false);
				if (num >= m_maxCreatures)
				{
					return;
				}
				GameObject val = (Object.op_Implicit((Object)(object)m_seperatePartner) ? m_seperatePartner : m_myPrefab);
				int nrOfInstances = SpawnSystem.GetNrOfInstances(val, ((Component)this).transform.position, m_partnerCheckRange, false, false);
				if (Object.op_Implicit((Object)(object)m_noPartnerOffspring) || ((Object.op_Implicit((Object)(object)m_seperatePartner) || nrOfInstances >= 2) && (!Object.op_Implicit((Object)(object)m_seperatePartner) || nrOfInstances >= 1)))
				{
					if (nrOfInstances > 0 && m_loveEffects != null)
					{
						m_loveEffects.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1);
					}
					int num2 = GetLovePoints() + 1;
					m_nview.GetZDO().Set(ZDOVars.s_lovePoints, num2, false);
					if (num2 >= m_requiredLovePoints)
					{
						m_nview.GetZDO().Set(ZDOVars.s_lovePoints, 0, false);
						MakePregnant();
					}
				}
			}
		}

		private void SpawnOffspring(bool parentIsTamed)
		{
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = m_offspringPrefab;
			if (Object.op_Implicit((Object)(object)m_noPartnerOffspring))
			{
				int nrOfInstances = SpawnSystem.GetNrOfInstances(Object.op_Implicit((Object)(object)m_seperatePartner) ? m_seperatePartner : m_myPrefab, ((Component)this).transform.position, m_partnerCheckRange, false, true);
				if ((!Object.op_Implicit((Object)(object)m_seperatePartner) && nrOfInstances < 2) || (Object.op_Implicit((Object)(object)m_seperatePartner) && nrOfInstances < 1))
				{
					val = m_noPartnerOffspring;
				}
			}
			Vector3 forward = ((Component)this).transform.forward;
			if (m_spawnRandomDirection)
			{
				float num = Random.Range(0f, (float)Math.PI * 2f);
				((Vector3)(ref forward))..ctor(Mathf.Cos(num), 0f, Mathf.Sin(num));
			}
			float num2 = ((m_spawnOffsetMax > 0f) ? Random.Range(m_spawnOffset, m_spawnOffsetMax) : m_spawnOffset);
			GameObject val2 = Object.Instantiate<GameObject>(val, ((Component)this).transform.position - forward * num2, Quaternion.LookRotation(-((Component)this).transform.forward, Vector3.up));
			Character component = val2.GetComponent<Character>();
			int num3 = Mathf.Max(m_minOffspringLevel, Object.op_Implicit((Object)(object)m_character) ? m_character.GetLevel() : m_minOffspringLevel);
			if (Object.op_Implicit((Object)(object)component))
			{
				component.SetTamed(parentIsTamed);
				component.SetLevel(num3);
			}
			else
			{
				ItemDrop component2 = val2.GetComponent<ItemDrop>();
				if (Object.op_Implicit((Object)(object)component2))
				{
					component2.SetQuality(num3);
				}
			}
			m_birthEffects.Create(val2.transform.position, Quaternion.identity, (Transform)null, 1f, -1);
		}

		public int GetLovePoints()
		{
			EnsureComponents();
			return ((Object)(object)m_nview != (Object)null && m_nview.IsValid()) ? m_nview.GetZDO().GetInt(ZDOVars.s_lovePoints, 0) : 0;
		}

		public bool ReadyForProcreation()
		{
			if (!m_enableProcreation || !m_canProcreateTamed)
			{
				return false;
			}
			if (!IsTamed())
			{
				return false;
			}
			return !IsPregnant() && !IsHungry();
		}

		private void MakePregnant()
		{
			EnsureComponents();
			if (Object.op_Implicit((Object)(object)m_nview) && m_nview.IsValid())
			{
				m_nview.GetZDO().Set(ZDOVars.s_pregnant, ZNet.instance.GetTime().Ticks);
			}
		}

		private void ResetPregnancy()
		{
			EnsureComponents();
			if (Object.op_Implicit((Object)(object)m_nview) && m_nview.IsValid())
			{
				m_nview.GetZDO().Set(ZDOVars.s_pregnant, 0L);
			}
		}

		private bool IsDue()
		{
			EnsureComponents();
			if (!Object.op_Implicit((Object)(object)m_nview) || !m_nview.IsValid())
			{
				return false;
			}
			long num = m_nview.GetZDO().GetLong(ZDOVars.s_pregnant, 0L);
			if (num == 0)
			{
				return false;
			}
			DateTime dateTime = new DateTime(num);
			return (ZNet.instance.GetTime() - dateTime).TotalSeconds > (double)m_pregnancyDuration;
		}

		private bool IsPregnant()
		{
			EnsureComponents();
			return (Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.GetZDO().GetLong(ZDOVars.s_pregnant, 0L) > 0;
		}

		public void CopyFromTameable(Tameable tameable)
		{
			if (Object.op_Implicit((Object)(object)tameable))
			{
				m_fedDuration = tameable.m_fedDuration;
				m_tamingTime = tameable.m_tamingTime;
				m_startsTamed = tameable.m_startsTamed;
				m_tamedEffect = tameable.m_tamedEffect;
				m_sootheEffect = tameable.m_sootheEffect;
				m_petEffect = tameable.m_petEffect;
				m_tamingSpeedMultiplierRange = tameable.m_tamingSpeedMultiplierRange;
				m_tamingBoostMultiplier = tameable.m_tamingBoostMultiplier;
				m_nameBeforeText = tameable.m_nameBeforeText;
				m_tameText = tameable.m_tameText;
			}
		}

		public void CopyFromProcreation(Procreation procreation)
		{
			if (Object.op_Implicit((Object)(object)procreation))
			{
				m_updateInterval = procreation.m_updateInterval;
				m_totalCheckRange = procreation.m_totalCheckRange;
				m_maxCreatures = procreation.m_maxCreatures;
				m_partnerCheckRange = procreation.m_partnerCheckRange;
				m_pregnancyChance = procreation.m_pregnancyChance;
				m_pregnancyDuration = procreation.m_pregnancyDuration;
				m_requiredLovePoints = procreation.m_requiredLovePoints;
				m_offspring = procreation.m_offspring;
				m_minOffspringLevel = procreation.m_minOffspringLevel;
				m_spawnOffset = procreation.m_spawnOffset;
				m_spawnOffsetMax = procreation.m_spawnOffsetMax;
				m_spawnRandomDirection = procreation.m_spawnRandomDirection;
				m_seperatePartner = procreation.m_seperatePartner;
				m_noPartnerOffspring = procreation.m_noPartnerOffspring;
				m_birthEffects = procreation.m_birthEffects;
				m_loveEffects = procreation.m_loveEffects;
			}
		}

		public void CopyFromMonsterAI(MonsterAI monsterAI)
		{
			if (Object.op_Implicit((Object)(object)monsterAI))
			{
				m_consumeItems = new List<ItemDrop>(monsterAI.m_consumeItems ?? new List<ItemDrop>());
				m_consumeRange = monsterAI.m_consumeRange;
				m_consumeSearchRange = monsterAI.m_consumeSearchRange;
				m_consumeSearchInterval = monsterAI.m_consumeSearchInterval;
				Humanoid component = ((Component)this).GetComponent<Humanoid>();
				if ((Object)(object)component != (Object)null)
				{
					m_consumeItemEffects = component.m_consumeItemEffects;
				}
			}
		}

		public void CopyValuesFrom(GameObject sourcePrefab)
		{
			if (Object.op_Implicit((Object)(object)sourcePrefab))
			{
				CopyFromTameable(sourcePrefab.GetComponent<Tameable>());
				CopyFromProcreation(sourcePrefab.GetComponent<Procreation>());
				CopyFromMonsterAI(sourcePrefab.GetComponent<MonsterAI>());
			}
		}

		public void SetConsumeItems(params ItemDrop[] items)
		{
			m_consumeItems = new List<ItemDrop>();
			if (items == null)
			{
				return;
			}
			foreach (ItemDrop val in items)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					m_consumeItems.Add(val);
				}
			}
		}

		public void SetProcreationEnabled(bool enabled)
		{
			m_enableProcreation = enabled;
			((MonoBehaviour)this).CancelInvoke("Procreate");
			if (enabled && ((Behaviour)this).isActiveAndEnabled)
			{
				EnsureComponents();
				if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
				{
					((MonoBehaviour)this).InvokeRepeating("Procreate", Random.Range(m_updateInterval, m_updateInterval + m_updateInterval * 0.5f), m_updateInterval);
				}
			}
		}
	}
	[DisallowMultipleComponent]
	internal sealed class MonsterHunger : MonoBehaviour
	{
		private static readonly int ZdoLastFedKey = StringExtensionMethods.GetStableHashCode("BalrondExtendedAnimals_LastFed");

		private static readonly List<ItemDrop> EmptyDiet = new List<ItemDrop>();

		public float hungerTime = 600f;

		public bool gateEatingByHunger = true;

		public float minHeal = 10f;

		public float minHealFraction = 0.1f;

		public float maxHealFraction = 0.25f;

		public bool clampToMissingHealth = true;

		private MonsterAI _ai;

		private ZNetView _nview;

		private Character _character;

		private Tameable _tameable;

		private List<ItemDrop> _cachedDiet;

		private bool _dietCached;

		private void Awake()
		{
			_ai = ((Component)this).GetComponent<MonsterAI>();
			_nview = ((Component)this).GetComponent<ZNetView>();
			_character = ((Component)this).GetComponent<Character>();
			_tameable = ((Component)this).GetComponent<Tameable>();
			if ((Object)(object)_ai == (Object)null || (Object)(object)_character == (Object)null)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			if ((Object)(object)_tameable != (Object)null)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			CacheDietIfNeeded();
			if (!_dietCached)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			MonsterAI ai = _ai;
			ai.m_onConsumedItem = (Action<ItemDrop>)Delegate.Combine(ai.m_onConsumedItem, new Action<ItemDrop>(OnConsumedItem));
			EnsureLastFedInitialized();
		}

		private void OnDestroy()
		{
			if ((Object)(object)_ai != (Object)null)
			{
				MonsterAI ai = _ai;
				ai.m_onConsumedItem = (Action<ItemDrop>)Delegate.Remove(ai.m_onConsumedItem, new Action<ItemDrop>(OnConsumedItem));
			}
		}

		private void Update()
		{
			if ((Object)(object)_ai == (Object)null)
			{
				((Behaviour)this).enabled = false;
			}
			else
			{
				if (!IsOwner() || !gateEatingByHunger)
				{
					return;
				}
				CacheDietIfNeeded();
				if (!_dietCached)
				{
					return;
				}
				if (IsHungryNow())
				{
					if (_ai.m_consumeItems == null || _ai.m_consumeItems.Count == 0 || _ai.m_consumeItems == EmptyDiet)
					{
						_ai.m_consumeItems = _cachedDiet;
					}
				}
				else if (_ai.m_consumeItems != EmptyDiet)
				{
					_ai.m_consumeItems = EmptyDiet;
				}
			}
		}

		public bool IsHungryNow()
		{
			DateTime lastFedTime = GetLastFedTime();
			return (GetSafeTime() - lastFedTime).TotalSeconds > (double)hungerTime;
		}

		private void OnConsumedItem(ItemDrop item)
		{
			if (IsOwner())
			{
				SetLastFedNow();
				HealFromConsumedItem(item);
			}
		}

		private void HealFromConsumedItem(ItemDrop item)
		{
			if ((Object)(object)_character == (Object)null)
			{
				return;
			}
			float health = _character.GetHealth();
			float maxHealth = _character.GetMaxHealth();
			if (maxHealth <= 0f)
			{
				return;
			}
			float num = maxHealth - health;
			if (!(num <= 0.01f))
			{
				float num2 = Mathf.Clamp01(minHealFraction);
				float num3 = Mathf.Clamp01(maxHealFraction);
				if (num3 < num2)
				{
					num3 = num2;
				}
				float num4 = maxHealth * Random.Range(num2, num3);
				if (num4 < minHeal)
				{
					num4 = minHeal;
				}
				if (clampToMissingHealth && num4 > num)
				{
					num4 = num;
				}
				if (!(num4 <= 0f))
				{
					_character.Heal(num4, true);
				}
			}
		}

		private void CacheDietIfNeeded()
		{
			if (!_dietCached && !((Object)(object)_ai == (Object)null) && _ai.m_consumeItems != null && _ai.m_consumeItems.Count > 0)
			{
				_cachedDiet = new List<ItemDrop>(_ai.m_consumeItems);
				_dietCached = true;
			}
		}

		private bool IsOwner()
		{
			if ((Object)(object)_nview == (Object)null)
			{
				return true;
			}
			return _nview.IsValid() && _nview.IsOwner();
		}

		private void EnsureLastFedInitialized()
		{
			ZDO zdo = GetZdo();
			if (zdo != null)
			{
				long num = zdo.GetLong(ZdoLastFedKey, 0L);
				if (num == 0)
				{
					SetLastFedNow();
				}
			}
		}

		private DateTime GetLastFedTime()
		{
			ZDO zdo = GetZdo();
			if (zdo == null)
			{
				return GetSafeTime();
			}
			long num = zdo.GetLong(ZdoLastFedKey, 0L);
			if (num <= 0)
			{
				return GetSafeTime();
			}
			try
			{
				return new DateTime(num);
			}
			catch
			{
				return GetSafeTime();
			}
		}

		private void SetLastFedNow()
		{
			ZDO zdo = GetZdo();
			if (zdo != null)
			{
				zdo.Set(ZdoLastFedKey, GetSafeTime().Ticks);
			}
		}

		private ZDO GetZdo()
		{
			if ((Object)(object)_nview == (Object)null || !_nview.IsValid())
			{
				return null;
			}
			return _nview.GetZDO();
		}

		private DateTime GetSafeTime()
		{
			return ((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTime() : DateTime.Now;
		}
	}
	[DisallowMultipleComponent]
	public sealed class WildProcreation : MonoBehaviour
	{
		private static readonly int ZdoHasWildChildKey = StringExtensionMethods.GetStableHashCode("Balrond_WildProcreation_HasChild");

		private static readonly int ZdoNextTryKey = StringExtensionMethods.GetStableHashCode("Balrond_WildProcreation_NextTry");

		private static readonly int ZdoChildBornKey = StringExtensionMethods.GetStableHashCode("Balrond_WildProcreation_ChildBorn");

		public float m_updateInterval = 120f;

		public float m_partnerCheckRange = 8f;

		public float m_totalCheckRange = 20f;

		public int m_maxCreatures = 6;

		public float m_spawnChance = 0.1f;

		public float m_initialDelay = 300f;

		public float m_failedTryCooldown = 180f;

		public GameObject m_offspring;

		public GameObject m_seperatePartner;

		public float m_spawnOffset = 2f;

		public float m_spawnOffsetMax;

		public bool m_spawnRandomDirection;

		public int m_minOffspringLevel;

		private ZNetView m_nview;

		private Character m_character;

		private BaseAI m_baseAI;

		private GameObject m_myPrefab;

		private GameObject m_offspringPrefab;

		private void Awake()
		{
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_character = ((Component)this).GetComponent<Character>();
			m_baseAI = ((Component)this).GetComponent<BaseAI>();
			if ((Object)(object)m_nview == (Object)null)
			{
				((Behaviour)this).enabled = false;
			}
			else
			{
				((MonoBehaviour)this).InvokeRepeating("TryWildProcreate", Random.Range(m_updateInterval, m_updateInterval * 1.5f), m_updateInterval);
			}
		}

		public void ConfigureFrom(Procreation source)
		{
			if (!((Object)(object)source == (Object)null))
			{
				m_updateInterval = Mathf.Max(60f, source.m_updateInterval * 2f);
				m_partnerCheckRange = source.m_partnerCheckRange;
				m_totalCheckRange = source.m_totalCheckRange;
				m_maxCreatures = Mathf.Max(2, source.m_maxCreatures);
				m_spawnChance = Mathf.Clamp(source.m_pregnancyChance * 0.35f, 0.02f, 0.15f);
				m_offspring = source.m_offspring;
				m_seperatePartner = source.m_seperatePartner;
				m_spawnOffset = source.m_spawnOffset;
				m_spawnOffsetMax = source.m_spawnOffsetMax;
				m_spawnRandomDirection = source.m_spawnRandomDirection;
				m_minOffspringLevel = source.m_minOffspringLevel;
			}
		}

		private void TryWildProcreate()
		{
			if (IsValidOwner() && !IsTamedSafe() && (!((Object)(object)m_baseAI != (Object)null) || !m_baseAI.IsAlerted()) && !HasAlreadyMadeChild() && CooldownReady())
			{
				if (!ResolvePrefabs())
				{
					SetNextTry(m_failedTryCooldown);
				}
				else if (HasNearbyOffspring())
				{
					SetPermanentChildBlock();
				}
				else if (TooManyNearby())
				{
					SetNextTry(m_failedTryCooldown);
				}
				else if (!HasPartner())
				{
					SetNextTry(m_failedTryCooldown);
				}
				else if (Random.value > m_spawnChance)
				{
					SetNextTry(m_failedTryCooldown);
				}
				else if (SpawnOffspring())
				{
					SetPermanentChildBlock();
				}
				else
				{
					SetNextTry(m_failedTryCooldown);
				}
			}
		}

		private bool ResolvePrefabs()
		{
			if ((Object)(object)ZNetScene.instance == (Object)null)
			{
				return false;
			}
			ZDO zdo = GetZdo();
			if (zdo == null)
			{
				return false;
			}
			if ((Object)(object)m_myPrefab == (Object)null)
			{
				m_myPrefab = ZNetScene.instance.GetPrefab(zdo.GetPrefab());
			}
			if ((Object)(object)m_offspringPrefab == (Object)null && (Object)(object)m_offspring != (Object)null)
			{
				m_offspringPrefab = ZNetScene.instance.GetPrefab(Utils.GetPrefabName(m_offspring));
			}
			return (Object)(object)m_myPrefab != (Object)null && (Object)(object)m_offspringPrefab != (Object)null;
		}

		private bool HasPartner()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = (((Object)(object)m_seperatePartner != (Object)null) ? m_seperatePartner : m_myPrefab);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			int nrOfInstances = SpawnSystem.GetNrOfInstances(val, ((Component)this).transform.position, m_partnerCheckRange, false, false);
			return ((Object)(object)m_seperatePartner == (Object)null) ? (nrOfInstances >= 2) : (nrOfInstances >= 1);
		}

		private bool TooManyNearby()
		{
			//IL_0032: 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)
			if ((Object)(object)m_myPrefab == (Object)null || (Object)(object)m_offspringPrefab == (Object)null)
			{
				return true;
			}
			int nrOfInstances = SpawnSystem.GetNrOfInstances(m_myPrefab, ((Component)this).transform.position, m_totalCheckRange, false, false);
			int nrOfInstances2 = SpawnSystem.GetNrOfInstances(m_offspringPrefab, ((Component)this).transform.position, m_totalCheckRange, false, false);
			return nrOfInstances + nrOfInstances2 >= m_maxCreatures;
		}

		private bool HasNearbyOffspring()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_offspringPrefab == (Object)null)
			{
				return false;
			}
			int nrOfInstances = SpawnSystem.GetNrOfInstances(m_offspringPrefab, ((Component)this).transform.position, m_totalCheckRange, false, false);
			return nrOfInstances > 0;
		}

		private bool SpawnOffspring()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_offspringPrefab == (Object)null)
			{
				return false;
			}
			Vector3 forward = ((Component)this).transform.forward;
			if (m_spawnRandomDirection)
			{
				float num = Random.Range(0f, (float)Math.PI * 2f);
				((Vector3)(ref forward))..ctor(Mathf.Cos(num), 0f, Mathf.Sin(num));
			}
			float num2 = ((m_spawnOffsetMax > 0f) ? Random.Range(m_spawnOffset, m_spawnOffsetMax) : m_spawnOffset);
			if (num2 <= 0f)
			{
				num2 = 2f;
			}
			GameObject val = Object.Instantiate<GameObject>(m_offspringPrefab, ((Component)this).transform.position - forward * num2, Quaternion.LookRotation(-((Component)this).transform.forward, Vector3.up));
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Character component = val.GetComponent<Character>();
			int num3 = (((Object)(object)m_character != (Object)null) ? m_character.GetLevel() : m_minOffspringLevel);
			int num4 = Mathf.Max(m_minOffspringLevel, num3);
			if ((Object)(object)component != (Object)null)
			{
				component.SetTamed(false);
				component.SetLevel(num4);
			}
			else
			{
				ItemDrop component2 = val.GetComponent<ItemDrop>();
				if ((Object)(object)component2 != (Object)null)
				{
					component2.SetQuality(num4);
				}
			}
			ZDO zdo = GetZdo();
			if (zdo != null)
			{
				zdo.Set(ZdoChildBornKey, GetTime().Ticks);
			}
			return true;
		}

		private bool IsValidOwner()
		{
			return (Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.IsOwner() && m_nview.GetZDO() != null && (Object)(object)ZNet.instance != (Object)null;
		}

		private bool IsTamedSafe()
		{
			if ((Object)(object)m_character == (Object)null)
			{
				return false;
			}
			try
			{
				return m_character.IsTamed();
			}
			catch
			{
				return false;
			}
		}

		private bool HasAlreadyMadeChild()
		{
			ZDO zdo = GetZdo();
			return zdo == null || zdo.GetBool(ZdoHasWildChildKey, false);
		}

		private void SetPermanentChildBlock()
		{
			ZDO zdo = GetZdo();
			if (zdo != null)
			{
				zdo.Set(ZdoHasWildChildKey, true);
				zdo.Set(ZdoNextTryKey, GetTime().AddYears(10).Ticks);
			}
		}

		private bool CooldownReady()
		{
			ZDO zdo = GetZdo();
			if (zdo == null)
			{
				return false;
			}
			long num = zdo.GetLong(ZdoNextTryKey, 0L);
			if (num <= 0)
			{
				SetNextTry(m_initialDelay + Random.Range(0f, m_initialDelay));
				return false;
			}
			try
			{
				return GetTime() >= new DateTime(num);
			}
			catch
			{
				SetNextTry(m_failedTryCooldown);
				return false;
			}
		}

		private void SetNextTry(float seconds)
		{
			ZDO zdo = GetZdo();
			if (zdo != null)
			{
				seconds = Mathf.Max(60f, seconds);
				zdo.Set(ZdoNextTryKey, GetTime().AddSeconds(seconds).Ticks);
			}
		}

		private ZDO GetZdo()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				return null;
			}
			return m_nview.GetZDO();
		}

		private DateTime GetTime()
		{
			return ((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetTime() : DateTime.Now;
		}
	}
	[BepInPlugin("balrond.astafaraios.BalrondMonsterMayhem", "BalrondMonsterMayhem", "0.3.7")]
	public class Launch : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(ZoneSystem), "SetupLocations")]
		private static class ZoneSystem_SetupLocations_Patch
		{
			private static void Postfix(ZoneSystem __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && __instance.m_locations != null)
				{
					locationBuilder.editLocations(__instance.m_locations);
				}
			}
		}

		[HarmonyPatch(typeof(Game), "Awake")]
		private static class Game_Awake_Patch
		{
			private static void Prefix()
			{
				SpawnSystemLifecyclePatch.Reset();
				SetupNewHudElements();
			}
		}

		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		private static class ZNetScene_Awake_Patch
		{
			private static void Prefix(ZNetScene __instance)
			{
				if ((Object)(object)__instance == (Object)null || __instance.m_prefabs == null)
				{
					Debug.LogWarning((object)(projectName + ": ZNetScene prefab list is not ready."));
					return;
				}
				modResourceLoader.AddPrefabsToZnetScene(__instance);
				monsterCloneService.RegisterVariants(__instance, MonsterVariantRegistry.Variants);
				if ((Object)(object)RandEventSystem.instance != (Object)null && RandEventSystem.instance.m_events != null)
				{
					eventBuilder.EditEvents(RandEventSystem.instance.m_events, __instance.m_prefabs);
					eventBuilder.AddNewEvents(RandEventSystem.instance.m_events, __instance.m_prefabs);
				}
				monsterManager.SetupMonsterList(__instance.m_prefabs);
				monsterManager.EditMonsters();
				CustomFactionRegistry.InitExampleRegistry();
				CreatureFactionRegistry.RegisterDefaultBiomeFactionMap();
				CreatureFactionRegistry.InitExampleRegistry();
				EggHatchService.SetupEggHatching(__instance);
				GrowthService.SetupGrowth(__instance);
				TamableService.SetupBreeding(__instance);
				CreatureSpawnerPrefabBuilder.RegisterAll(__instance);
				if (!IsDedicatedServer())
				{
					ShaderReplacment.runMaterialFix();
				}
			}
		}

		private readonly Harmony harmony = new Harmony("balrond.astafaraios.BalrondMonsterMayhem");

		public const string PluginGUID = "balrond.astafaraios.BalrondMonsterMayhem";

		public const string PluginName = "BalrondMonsterMayhem";

		public const string PluginVersion = "0.3.7";

		public static readonly ModResourceLoader modResourceLoader = new ModResourceLoader();

		public static readonly DatabaseAddMethods databaseAddMethods = new DatabaseAddMethods();

		public static readonly MonsterManager monsterManager = new MonsterManager();

		public static readonly SpawnerBuilder spawnerBuilder = new SpawnerBuilder();

		public static readonly ItemEdits itemEdits = new ItemEdits();

		public static readonly EventBuilder eventBuilder = new EventBuilder();

		public static readonly MonsterFeeding monsterFeeding = new MonsterFeeding();

		public static readonly LocationBuilder locationBuilder = new LocationBuilder();

		public static readonly JsonLoader jsonLoader = new JsonLoader();

		public static readonly MonsterCloneService monsterCloneService = new MonsterCloneService();

		public static GameObject gui;

		public static GameObject gui2;

		public static string projectName = "BalrondMonsterMayhem";

		public static GameObject RootObject;

		public static GameObject PrefabContainer;

		private static readonly string GUI_PATH = "_GameMain/LoadingGUI/PixelFix/IngameGui/EnemyHud/HudRoot/HudBase";

		private static readonly string GUI_BOSS_PATH = "_GameMain/LoadingGUI/PixelFix/IngameGui/EnemyHud/HudRoot/HudBaseBoss";

		private void Awake()
		{
			jsonLoader.loadJson();
			CreatePrefabContainer();
			modResourceLoader.loadAssets();
			monsterManager.RegisterLootAliases(MonsterVariantRegistry.BuildLootAliasMap());
			harmony.PatchAll();
		}

		public void Start()
		{
			RegisterUpgrade("trollcaveRemove", "remove vanilla troll caves before moving them", LocationBuilder.vanillaLocationsYouEdit, "locations_remove  biomes=BlackForest");
			RegisterUpgrade("trollcaveAdd", "add updated troll caves to Moutains and Deepnorth", LocationBuilder.vanillaLocationsYouEdit, "locations_add");
			Upgrade.Register("BalrondMonsterMayhem_fixZoneAfterTroll", "covers spots left by removing caves", "vegetation_add biomes=BlackForest start");
		}

		private void RegisterUpgrade(string keySuffix, string description, IEnumerable<string> names, string lineName)
		{
			string name = "BalrondMonsterMayhem_" + keySuffix;
			string text = string.Format("{0} {1} start", lineName, string.Join(",", names));
			Upgrade.Register(name, description, text);
		}

		public void CreatePrefabContainer()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			if (!((Object)(object)RootObject != (Object)null) || !((Object)(object)PrefabContainer != (Object)null))
			{
				RootObject = new GameObject("_ValheimReforgedRoot");
				Object.DontDestroyOnLoad((Object)(object)RootObject);
				PrefabContainer = new GameObject("Prefabs");
				PrefabContainer.transform.parent = RootObject.transform;
				PrefabContainer.SetActive(false);
			}
		}

		public static GameObject cloneMe(GameObject source, string name)
		{
			GameObject val = Object.Instantiate<GameObject>(source, PrefabContainer.transform);
			((Object)val).name = name;
			fixMaterials(val, source);
			val.SetActive(true);
			return val;
		}

		public static GameObject fixMaterials(GameObject clone, GameObject source)
		{
			MeshRenderer[] componentsInChildren = source.GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer val in componentsInChildren)
			{
				MeshRenderer[] componentsInChildren2 = clone.GetComponentsInChildren<MeshRenderer>();
				foreach (MeshRenderer val2 in componentsInChildren2)
				{
					if (((Object)val).name == ((Object)val2).name)
					{
						((Renderer)val2).materials = ((Renderer)val).sharedMaterials;
						((Renderer)val2).sharedMaterials = ((Renderer)val).sharedMaterials;
						break;
					}
				}
			}
			return clone;
		}

		private void OnDestroy()
		{
			harmony.UnpatchSelf();
		}

		public static bool IsObjectDBValid()
		{
			return (Object)(object)ObjectDB.instance != (Object)null && ObjectDB.instance.m_items.Count != 0 && ObjectDB.instance.m_recipes.Count != 0 && (Object)(object)ObjectDB.instance.GetItemPrefab("Amber") != (Object)null;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(RandEventSystem), "StartRandomEvent")]
		private static void RandEventSystem_StartRandomEvent(ref bool __runOriginal)
		{
			int nrOfPlayers = ZNet.instance.GetNrOfPlayers();
			__runOriginal = nrOfPlayers >= 2;
			if (!__runOriginal && !ZNet.IsSinglePlayer)
			{
				Debug.Log((object)$"Not enough players online for raid. Min player count: {2}, currently online: {nrOfPlayers}");
			}
		}

		public static void SetupNewHudElements()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			if (!(((Scene)(ref activeScene)).name != "main"))
			{
				if ((Object)(object)gui == (Object)null)
				{
					gui = GameObject.Find(GUI_PATH);
				}
				if ((Object)(object)gui2 == (Object)null)
				{
					gui2 = GameObject.Find(GUI_BOSS_PATH);
				}
				SetupRegularHud();
				SetupBossHud();
			}
		}

		private static void SetupRegularHud()
		{
			if (!((Object)(object)gui == (Object)null) && modResourceLoader != null)
			{
				if ((Object)(object)modResourceLoader.lvl4 == (Object)null)
				{
					modResourceLoader.LoadNewStars();
				}
				AttachToGui(gui, modResourceLoader.lvl4, modResourceLoader.lvl5, modResourceLoader.lvl6, modResourceLoader.lvl7);
			}
		}

		private static void SetupBossHud()
		{
			if (!((Object)(object)gui2 == (Object)null) && modResourceLoader != null)
			{
				if ((Object)(object)modResourceLoader.lvl2boss == (Object)null)
				{
					modResourceLoader.LoadNewBossStars();
				}
				AttachToGui(gui2, modResourceLoader.lvl2boss, modResourceLoader.lvl3boss, modResourceLoader.lvl4boss, modResourceLoader.lvl5boss, modResourceLoader.lvl6boss, modResourceLoader.lvl7boss);
			}
		}

		private static void AttachToGui(GameObject parent, params GameObject[] elements)
		{
			if ((Object)(object)parent == (Object)null || elements == null)
			{
				return;
			}
			foreach (GameObject val in elements)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.transform.SetParent(parent.transform, false);
				}
			}
		}

		private static bool IsDedicatedServer()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			return (int)SystemInfo.graphicsDeviceType == 4;
		}
	}
	public class BaseLevelEffectSetupValue
	{
		public float scale = 1.1f;

		public float saturation = 0.5f;

		public float hue = -0.1f;

		public float value = -0.1f;

		public bool setEmmisive = false;

		public float sumValue = 0.05f;

		public LevelSetup setup = null;

		public GameObject enabledObject = null;

		public GameObject enabledObjectLevel2 = null;

		public GameObject enabledObjectLevel3 = null;

		public bool setEmissive = false;

		public Color emissive = Color.white;

		public void GetSetup(LevelEffects levelEffects)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)levelEffects == (Object)null)
			{
				Debug.LogWarning((object)"LevelEffects is null");
				return;
			}
			List<LevelSetup> levelSetups = levelEffects.m_levelSetups;
			int num = levelSetups?.Count ?? 0;
			if (num > 0)
			{
				setup = levelSetups.Last();
				ApplySetupValues();
			}
			else
			{
				SetDefaultValues(num, ((Component)levelEffects).transform.localScale.y);
			}
			HandleCharacterSpecificAdjustments(levelEffects);
		}

		private void ApplySetupValues()
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (setup != null)
			{
				scale = setup.m_scale;
				saturation = setup.m_saturation;
				hue = setup.m_hue;
				value = setup.m_value;
				enabledObject = setup.m_enableObject;
				enabledObjectLevel2 = enabledObject;
				enabledObjectLevel3 = enabledObject;
				emissive = setup.m_emissiveColor;
				setEmissive = setup.m_setEmissiveColor;
			}
		}

		private void SetDefaultValues(int levels, float baseScale)
		{
			switch (levels)
			{
			case 0:
				scale = baseScale;
				saturation = 0f;
				hue = 0f;
				value = 0f;
				break;
			case 1:
				scale = baseScale + 0.05f;
				saturation = 0.5f;
				hue = -0.05f;
				value = -0.05f;
				break;
			case 2:
				scale = baseScale + 0.1f;
				saturation = 0.5f;
				hue = -0.1f;
				value = -0.1f;
				break;
			}
		}

		private void HandleCharacterSpecificAdjustments(LevelEffects levelEffects)
		{
			Character character = levelEffects.m_character;
			object obj;
			if (character == null)
			{
				obj = null;
			}
			else
			{
				GameObject gameObject = ((Component)character).gameObject;
				obj = ((gameObject != null) ? ((Object)gameObject).name : null);
			}
			string text = (string)obj;
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			string text2 = text;
			string text3 = text2;
			if (!(text3 == "Deer"))
			{
				if (text3 == "Boar")
				{
					EditBoar(levelEffects);
				}
			}
			else
			{
				EditDeer(levelEffects);
			}
		}

		private void EditDeer(LevelEffects levelEffects)
		{
			if (levelEffects.m_levelSetups.Count >= 2)
			{
				GameObject enableObject = levelEffects.m_levelSetups[0].m_enableObject;
				GameObject enableObject2 = levelEffects.m_levelSetups[1].m_enableObject;
				enabledObjectLevel2 = enableObject;
				enabledObjectLevel3 = enableObject2;
				Transform parent = enableObject.transform.parent;
				object obj;
				if (parent == null)
				{
					obj = null;
				}
				else
				{
					Transform obj2 = parent.Find("Antler1");
					obj = ((obj2 != null) ? ((Component)obj2).gameObject : null);
				}
				GameObject val = (GameObject)obj;
				if ((Object)(object)val != (Object)null)
				{
					enabledObject = val;
					levelEffects.m_levelSetups[0].m_enableObject = val;
					levelEffects.m_levelSetups[1].m_enableObject = val;
				}
			}
		}

		private void EditBoar(LevelEffects levelEffects)
		{
		}
	}
	public sealed class CreatureSpawnerDefinition
	{
		public readonly string CreaturePrefabName;

		public string TemplateSpawnerName;

		public string SpawnerPrefabName;

		public int? MaxLevel;

		public int? MinLevel;

		public float? LevelupChance;

		public float? RespawnTimeMinutes;

		public float? TriggerDistance;

		public float? TriggerNoise;

		public bool? SpawnAtNight;

		public bool? SpawnAtDay;

		public bool? RequireSpawnArea;

		public bool? SpawnInPlayerBase;

		public bool? WakeUpAnimation;

		public int? SpawnInterval;

		public string RequiredGlobalKey;

		public string BlockingGlobalKey;

		public bool? SetPatrolSpawnPoint;

		public int? SpawnGroupID;

		public int? MaxGroupSpawned;

		public float? SpawnGroupRadius;

		public float? SpawnerWeight;

		public Action<GameObject, CreatureSpawner> Configure;

		public CreatureSpawnerDefinition(string creaturePrefabName)
		{
			CreaturePrefabName = creaturePrefabName;
		}

		public string GetSpawnerPrefabName()
		{
			if (!string.IsNullOrEmpty(SpawnerPrefabName))
			{
				return SpawnerPrefabName;
			}
			if (string.IsNullOrEmpty(CreaturePrefabName))
			{
				return string.Empty;
			}
			if (CreaturePrefabName.Contains("_bal"))
			{
				return "Spawner_" + CreaturePrefabName;
			}
			return "Spawner_" + CreaturePrefabName + "_bal";
		}
	}
	public static class CreatureSpawnerRegistry
	{
		public static readonly List<CreatureSpawnerDefinition> Spawners = new List<CreatureSpawnerDefinition>
		{
			new CreatureSpawnerDefinition("Bjorn")
			{
				TemplateSpawnerName = "Spawner_Troll",
				SetPatrolSpawnPoint = true
			},
			new CreatureSpawnerDefinition("BjornCub_bal")
			{
				TemplateSpawnerName = "Spawner_Goblin",
				SetPatrolSpawnPoint = true
			},
			new CreatureSpawnerDefinition("TrollBrute_bal")
			{
				TemplateSpawnerName = "Spawner_Goblin",
				SetPatrolSpawnPoint = true
			},
			new CreatureSpawnerDefinition("BlobAcid_bal")
			{
				TemplateSpawnerName = "Spawner_Blob",
				SetPatrolSpawnPoint = true
			},
			new CreatureSpawnerDefinition("Wolf")
			{
				TemplateSpawnerName = "Spawner_Boar",
				MaxLevel = 3,
				MinLevel = 1,
				SetPatrolSpawnPoint = true
			},
			new CreatureSpawnerDefinition("Ulv")
			{
				TemplateSpawnerName = "Spawner_Boar",
				SetPatrolSpawnPoint = true
			},
			new CreatureSpawnerDefinition("GhostYagluth_bal")
			{
				TemplateSpawnerName = "Spawner_Skeleton",
				SetPatrolSpawnPoint = true
			},
			new CreatureSpawnerDefinition("Ghost_bal")
			{
				TemplateSpawnerName = "Spawner_Skeleton",
				SetPatrolSpawnPoint = true
			},
			new CreatureSpawnerDefinition("Ghost")
			{
				TemplateSpawnerName = "Spawner_Skeleton",
				SetPatrolSpawnPoint = true
			},
			new CreatureSpawnerDefinition("Neck")
			{
				TemplateSpawnerName = "Spawner_Boar",
				SetPatrolSpawnPoint = true
			},
			new CreatureSpawnerDefinition("goblin_skeleton_bal")
			{
				TemplateSpawnerName = "Spawner_Skeleton",
				SetPatrolSpawnPoint = true
			}
		};
	}
	public static class CreatureSpawnerPrefabBuilder
	{
		private const string DefaultTemplateName = "Spawner_Goblin";

		private static readonly HashSet<string> RegisteredSpawnerNames = new HashSet<string>(StringComparer.Ordinal);

		private static readonly HashSet<int> RegisteredSpawnerHashes = new HashSet<int>();

		public static void RegisterAll(ZNetScene zNetScene)
		{
			if ((Object)(object)zNetScene == (Object)null || zNetScene.m_prefabs == null)
			{
				Debug.LogWarning((object)"[BalrondExtendedAnimals] CreatureSpawner RegisterAll skipped: ZNetScene or prefab list is null.");
				return;
			}
			for (int i = 0; i < CreatureSpawnerRegistry.Spawners.Count; i++)
			{
				Register(zNetScene, CreatureSpawnerRegistry.Spawners[i]);
			}
		}

		public static GameObject Register(ZNetScene zNetScene, CreatureSpawnerDefinition definition)
		{
			if ((Object)(object)zNetScene == (Object)null || zNetScene.m_prefabs == null || definition == null)
			{
				return null;
			}
			if (string.IsNullOrEmpty(definition.CreaturePrefabName))
			{
				Debug.LogWarning((object)"[BalrondExtendedAnimals] CreatureSpawner build skipped: CreaturePrefabName is empty.");
				return null;
			}
			string spawnerPrefabName = definition.GetSpawnerPrefabName();
			if (string.IsNullOrEmpty(spawnerPrefabName))
			{
				Debug.LogWarning((object)("[BalrondExtendedAnimals] CreatureSpawner build skipped: target spawner name is empty for creature " + definition.CreaturePrefabName));
				return null;
			}
			int stableHashCode = StringExtensionMethods.GetStableHashCode(spawnerPrefabName);
			if (RegisteredSpawnerNames.Contains(spawnerPrefabName) || RegisteredSpawnerHashes.Contains(stableHashCode))
			{
				Debug.LogWarning((object)("[BalrondExtendedAnimals] CreatureSpawner already registered by this builder, skipping: " + spawnerPrefabName));
				return null;
			}
			GameObject val = FindPrefabByNameOrHash(zNetScene, spawnerPrefabName, stableHashCode);
			if ((Object)(object)val != (Object)null)
			{
				Debug.LogWarning((object)("[BalrondExtendedAnimals] CreatureSpawner already exists in ZNetScene, skipping without modifying it: " + spawnerPrefabName));
				RegisteredSpawnerNames.Add(spawnerPrefabName);
				RegisteredSpawnerHashes.Add(stableHashCode);
				return null;
			}
			GameObject val2 = FindPrefab(zNetScene, definition.CreaturePrefabName);
			if ((Object)(object)val2 == (Object)null)
			{
				Debug.LogWarning((object)("[BalrondExtendedAnimals] CreatureSpawner build skipped. Creature prefab not found: " + definition.CreaturePrefabName));
				return null;
			}
			GameObject val3 = FindTemplateSpawner(zNetScene, definition);
			bool createdFromScratch = (Object)(object)val3 == (Object)null;
			GameObject val4 = CreateSpawnerPrefab(val3, spawnerPrefabName);
			if ((Object)(object)val4 == (Object)null)
			{
				Debug.LogWarning((object)("[BalrondExtendedAnimals] CreatureSpawner build failed: " + spawnerPrefabName));
				return null;
			}
			ApplyDefinition(val4, val2, definition, createdFromScratch);
			zNetScene.m_prefabs.Add(val4);
			RegisteredSpawnerNames.Add(spawnerPrefabName);
			RegisteredSpawnerHashes.Add(stableHashCode);
			Debug.Log((object)("[BalrondExtendedAnimals] Registered generated creature spawner: " + spawnerPrefabName + " -> " + definition.CreaturePrefabName));
			return val4;
		}

		private static GameObject FindTemplateSpawner(ZNetScene zNetScene, CreatureSpawnerDefinition definition)
		{
			GameObject val = null;
			if (definition != null && !string.IsNullOrEmpty(definition.TemplateSpawnerName))
			{
				val = FindPrefab(zNetScene, definition.TemplateSpawnerName);
				if ((Object)(object)val == (Object)null)
				{
					Debug.LogWarning((object)("[BalrondExtendedAnimals] CreatureSpawner template not found: " + definition.TemplateSpawnerName + ". Falling back to default template."));
				}
				else if ((Object)(object)val.GetComponent<CreatureSpawner>() == (Object)null)
				{
					Debug.LogWarning((object)("[BalrondExtendedAnimals] CreatureSpawner template has no CreatureSpawner component: " + definition.TemplateSpawnerName + ". Falling back to default template."));
					val = null;
				}
			}
			if ((Object)(object)val == (Object)null && !string.IsNullOrEmpty("Spawner_Goblin"))
			{
				val = FindPrefab(zNetScene, "Spawner_Goblin");
				if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<CreatureSpawner>() == (Object)null)
				{
					val = null;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				val = FindAnyCreatureSpawnerPrefab(zNetScene);
			}
			return val;
		}

		private static GameObject CreateSpawnerPrefab(GameObject template, string newName)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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)
			GameObject val = new GameObject(newName);
			val.SetActive(false);
			if ((Object)(object)template != (Object)null)
			{
				val.transform.position = template.transform.position;
				val.transform.rotation = template.transform.rotation;
				val.transform.localScale = template.transform.localScale;
			}
			ZNetView val2 = val.AddComponent<ZNetView>();
			val2.m_persistent = true;
			val2.m_distant = false;
			val2.m_type = (ObjectType)0;
			val2.m_syncInitialScale = false;
			CreatureSpawner target = val.AddComponent<CreatureSpawner>();
			if ((Object)(object)template != (Object)null)
			{
				CreatureSpawner component = template.GetComponent<CreatureSpawner>();
				if ((Object)(object)component != (Object)null)
				{
					CopyCreatureSpawner(component, target);
				}
			}
			return val;
		}

		private static void CopyCreatureSpawner(CreatureSpawner source, CreatureSpawner target)
		{
			if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null))
			{
				target.m_creaturePrefab = source.m_creaturePrefab;
				target.m_maxLevel = source.m_maxLevel;
				target.m_minLevel = source.m_minLevel;
				target.m_levelupChance = source.m_levelupChance;
				target.m_respawnTimeMinuts = source.m_respawnTimeMinuts;
				target.m_triggerDistance = source.m_triggerDistance;
				target.m_triggerNoise = source.m_triggerNoise;
				target.m_spawnAtNight = source.m_spawnAtNight;
				target.m_spawnAtDay = source.m_spawnAtDay;
				target.m_requireSpawnArea = source.m_requireSpawnArea;
				target.m_spawnInPlayerBase = source.m_spawnInPlayerBase;
				target.m_wakeUpAnimation = source.m_wakeUpAnimation;
				target.m_spawnInterval = source.m_spawnInterval;
				target.m_requiredGlobalKey = source.m_requiredGlobalKey;
				target.m_blockingGlobalKey = source.m_blockingGlobalKey;
				target.m_setPatrolSpawnPoint = source.m_setPatrolSpawnPoint;
				target.m_spawnGroupID = source.m_spawnGroupID;
				target.m_maxGroupSpawned = source.m_maxGroupSpawned;
				target.m_spawnGroupRadius = source.m_spawnGroupRadius;
				target.m_spawnerWeight = source.m_spawnerWeight;
			}
		}

		private static void ApplyDefinition(GameObject spawnerPrefab, GameObject creaturePrefab, CreatureSpawnerDefinition definition, bool createdFromScratch)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)spawnerPrefab == (Object)null || (Object)(object)creaturePrefab == (Object)null || definition == null)
			{
				return;
			}
			ZNetView val = spawnerPrefab.GetComponent<ZNetView>();
			if ((Object)(object)val == (Object)null)
			{
				bool activeSelf = spawnerPrefab.activeSelf;
				if (activeSelf)
				{
					spawnerPrefab.SetActive(false);
				}
				val = spawnerPrefab.AddComponent<ZNetView>();
				if (activeSelf)
				{
					spawnerPrefab.SetActive(true);
				}
			}
			val.m_persistent = true;
			val.m_distant = false;
			val.m_type = (ObjectType)0;
			val.m_syncInitialScale = false;
			CreatureSpawner val2 = spawnerPrefab.GetComponent<CreatureSpawner>();
			if ((Object)(object)val2 == (Object)null)
			{
				bool activeSelf2 = spawnerPrefab.activeSelf;
				if (activeSelf2)
				{
					spawnerPrefab.SetActive(false);
				}
				val2 = spawnerPrefab.AddComponent<CreatureSpawner>();
				if (activeSelf2)
				{
					spawnerPrefab.SetActive(true);
				}
			}
			if (createdFromScratch)
			{
				ApplyScratchDefaults(val2);
			}
			val2.m_creaturePrefab = creaturePrefab;
			if (definition.MaxLevel.HasValue)
			{
				val2.m_maxLevel = definition.MaxLevel.Value;
			}
			if (definition.MinLevel.HasValue)
			{
				val2.m_minLevel = definition.MinLevel.Value;
			}
			if (definition.LevelupChance.HasValue)
			{
				val2.m_levelupChance = definition.LevelupChance.Value;
			}
			if (definition.RespawnTimeMinutes.HasValue)
			{
				val2.m_respawnTimeMinuts = definition.RespawnTimeMinutes.Value;
			}
			if (definition.TriggerDistance.HasValue)
			{
				val2.m_triggerDistance = definition.TriggerDistance.Value;
			}
			if (definition.TriggerNoise.HasValue)
			{
				val2.m_triggerNoise = definition.TriggerNoise.Value;
			}
			if (definition.SpawnAtNight.HasValue)
			{
				val2.m_spawnAtNight = definition.SpawnAtNight.Value;
			}
			if (definition.SpawnAtDay.HasValue)
			{
				val2.m_spawnAtDay = definition.SpawnAtDay.Value;
			}
			if (definition.RequireSpawnArea.HasValue)
			{
				val2.m_requireSpawnArea = definition.RequireSpawnArea.Value;
			}
			if (definition.SpawnInPlayerBase.HasValue)
			{
				val2.m_spawnInPlayerBase = definition.SpawnInPlayerBase.Value;
			}
			if (definition.WakeUpAnimation.HasValue)
			{
				val2.m_wakeUpAnimation = definition.WakeUpAnimation.Value;
			}
			if (definition.SpawnInterval.HasValue)
			{
				val2.m_spawnInterval = definition.SpawnInterval.Value;
			}
			if (definition.RequiredGlobalKey != null)
			{
				val2.m_requiredGlobalKey = definition.RequiredGlobalKey;
			}
			if (definition.BlockingGlobalKey != null)
			{
				val2.m_blockingGlobalKey = definition.BlockingGlobalKey;
			}
			if (definition.SetPatrolSpawnPoint.HasValue)
			{
				val2.m_setPatrolSpawnPoint = definition.SetPatrolSpawnPoint.Value;
			}
			if (definition.SpawnGroupID.HasValue)
			{
				val2.m_spawnGroupID = definition.SpawnGroupID.Value;
			}
			if (definition.MaxGroupSpawned.HasValue)
			{
				val2.m_maxGroupSpawned = definition.MaxGroupSpawned.Value;
			}
			if (definition.SpawnGroupRadius.HasValue)
			{
				val2.m_spawnGroupRadius = definition.SpawnGroupRadius.Value;
			}
			if (definition.SpawnerWeight.HasValue)
			{
				val2.m_spawnerWeight = definition.SpawnerWeight.Value;
			}
			if (definition.Configure != null)
			{
				definition.Configure(spawnerPrefab, val2);
			}
		}

		private static void ApplyScratchDefaults(CreatureSpawner spawner)
		{
			if (!((Object)(object)spawner == (Object)null))
			{
				spawner.m_maxLevel = 1;
				spawner.m_minLevel = 1;
				spawner.m_levelupChance = 10f;
				spawner.m_respawnTimeMinuts = 20f;
				spawner.m_triggerDistance = 60f;
				spawner.m_triggerNoise = 0f;
				spawner.m_spawnAtNight = true;
				spawner.m_spawnAtDay = true;
				spawner.m_requireSpawnArea = false;
				spawner.m_spawnInPlayerBase = false;
				spawner.m_wakeUpAnimation = false;
				spawner.m_spawnInterval = 5;
				spawner.m_requiredGlobalKey = "";
				spawner.m_blockingGlobalKey = "";
				spawner.m_setPatrolSpawnPoint = true;
				spawner.m_spawnGroupID = 0;
				spawner.m_maxGroupSpawned = 1;
				spawner.m_spawnGroupRadius = 0f;
				spawner.m_spawnerWeight = 1f;
			}
		}

		private static GameObject FindPrefab(ZNetScene zNetScene, string prefabName)
		{
			if ((Object)(object)zNetScene == (Object)null || zNetScene.m_prefabs == null || string.IsNullOrEmpty(prefabName))
			{
				return null;
			}
			for (int i = 0; i < zNetScene.m_prefabs.Count; i++)
			{
				GameObject val = zNetScene.m_prefabs[i];
				if ((Object)(object)val != (Object)null && ((Object)val).name == prefabName)
				{
					return val;
				}
			}
			return null;
		}

		private static GameObject FindPrefabByNameOrHash(ZNetScene zNetScene, string prefabName, int stableHash)
		{
			if ((Object)(object)zNetScene == (Object)null || zNetScene.m_prefabs == null || string.IsNullOrEmpty(prefabName))
			{
				return null;
			}
			for (int i = 0; i < zNetScene.m_prefabs.Count; i++)
			{
				GameObject val = zNetScene.m_prefabs[i];
				if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name) && (((Object)val).name == prefabName || StringExtensionMethods.GetStableHashCode(((Object)val).name) == stableHash))
				{
					return val;
				}
			}
			return null;
		}

		private static GameObject FindAnyCreatureSpawnerPrefab(ZNetScene zNetScene)
		{
			if ((Object)(object)zNetScene == (Object)null || zNetScene.m_prefabs == null)
			{
				return null;
			}
			for (int i = 0; i < zNetScene.m_prefabs.Count; i++)
			{
				GameObject val = zNetScene.m_prefabs[i];
				if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<CreatureSpawner>() != (Object)null)
				{
					return val;
				}
			}
			return null;
		}
	}
	public static class EggHatchService
	{
		private sealed class EggGrowConfig
		{
			public string GrowTo { get; set; }

			public bool Tame { get; set; }

			public bool RequireFire { get; set; }

			public bool RequireRoof { get; set; }

			public int GrowupTime { get; set; }
		}

		private static readonly Dictionary<string, EggGrowConfig> EggGrowConfigs = new Dictionary<string, EggGrowConfig>
		{
			{
				"VoltureEgg",
				new EggGrowConfig
				{
					GrowTo = "VoltureNestling_bal",
					Tame = true,
					RequireFire = true,
					RequireRoof = false,
					GrowupTime = 6000
				}
			},
			{
				"DragonEgg",
				new EggGrowConfig
				{
					GrowTo = "Hatchling",
					Tame = false,
					RequireFire = true,
					RequireRoof = false,
					GrowupTime = 9000
				}
			},
			{
				"CrowEgg_bal",
				new EggGrowConfig
				{
					GrowTo = "CrowNestling_bal",
					Tame = true,
					RequireFire = true,
					RequireRoof = false,
					GrowupTime = 4000
				}
			},
			{
				"SerpentEgg_bal",
				new EggGrowConfig
				{
					GrowTo = "Serpentling_bal",
					Tame = false,
					RequireFire = false,
					RequireRoof = false,
					GrowupTime = 7000
				}
			},
			{
				"LeechEgg_bal",
				new EggGrowConfig
				{
					GrowTo = "LeechLarva_bal",
					Tame = false,
					RequireFire = false,
					RequireRoof = false,
					GrowupTime = 5000
				}
			},
			{
				"Larva_bal",
				new EggGrowConfig
				{
					GrowTo = "SeekerBrood",
					Tame = false,
					RequireFire = true,
					RequireRoof = false,
					GrowupTime = 6000
				}
			}
		};

		public static void SetupEggHatching(ZNetScene zNetScene)
		{
			if ((Object)(object)zNetScene == (Object)null || zNetScene.m_prefabs == null)
			{
				return;
			}
			GameObject val = TamableService.FindPrefabInZnet("ChickenEgg", zNetScene);
			EggGrow val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<EggGrow>() : null);
			if ((Object)(object)val2 == (Object)null)
			{
				Debug.LogWarning((object)(Launch.projectName + ": ChickenEgg EggGrow template not found."));
			}
			foreach (KeyValuePair<string, EggGrowConfig> eggGrowConfig in EggGrowConfigs)
			{
				string key = eggGrowConfig.Key;
				EggGrowConfig value = eggGrowConfig.Value;
				GameObject val3 = TamableService.FindPrefabInZnet(key, zNetScene);
				if ((Object)(object)val3 == (Object)null)
				{
					Debug.LogWarning((object)(Launch.projectName + ": egg prefab not found in ZNetScene: " + key));
					continue;
				}
				GameObject val4 = TamableService.FindPrefabInZnet(value.GrowTo, zNetScene);
				if ((Object)(object)val4 == (Object)null)
				{
					Debug.LogWarning((object)(Launch.projectName + ": egg grown prefab not found in ZNetScene: " + value.GrowTo + " for " + ((Object)val3).name));
				}
				else
				{
					AddEggGrow(val3, val2, value, zNetScene);
				}
			}
		}

		private static void LogPossiblePrefabMatches(ZNetScene zNetScene, string missingName)
		{
			if ((Object)(object)zNetScene == (Object)null || zNetScene.m_prefabs == null || string.IsNullOrEmpty(missingName))
			{
				return;
			}
			string text = missingName.Replace("(Clone)", "").Replace("_bal", "").Replace("_", "")
				.ToLowerInvariant();
			foreach (G