Decompiled source of Taming v0.1.21

BepInEx/plugins/Zephyrfit-Taming/ZephyrfitTaming.dll

Decompiled an hour ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using LetMeTameYou;
using LetMeTameYou.RPC;
using Microsoft.CodeAnalysis;
using MountUp;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Rendering;
using UnityEngine.TextCore;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("ZephyrfitTaming")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.21.0")]
[assembly: AssemblyInformationalVersion("0.1.21")]
[assembly: AssemblyProduct("ZephyrfitTaming")]
[assembly: AssemblyTitle("ZephyrfitTaming")]
[assembly: AssemblyVersion("0.1.21.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Zephyrfit.Taming
{
	internal static class AnimalSexState
	{
		internal const string Key = "zf_sex_v1";

		private static readonly Dictionary<string, ConfigEntry<SexMode>> modes = new Dictionary<string, ConfigEntry<SexMode>>();

		private static float next;

		internal static void Configure(ConfigFile config)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			string[] array = new string[5] { "Bjorn", "Hare", "Lox", "Wolf", "Boar" };
			foreach (string text in array)
			{
				modes[text] = config.Bind<SexMode>("Server Rules", text + " sex mode", SexMode.MaleFemale, new ConfigDescription("Server species rule: MaleFemale = opposite sexes and female pregnancy; Hermaphrodite = two distinct animals, one pregnancy per pairing; Disabled = native sex-free rules. Existing pregnancy survives every transition; persisted male/female assignment is retained when hidden.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					IsAdminOnly = true
				} }));
			}
		}

		internal static string Species(Component c)
		{
			if (!Object.op_Implicit((Object)(object)c))
			{
				return "";
			}
			Growup component = c.GetComponent<Growup>();
			if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.m_grownPrefab))
			{
				return Utils.GetPrefabName(c.gameObject);
			}
			return Utils.GetPrefabName(component.m_grownPrefab);
		}

		internal static SexMode Mode(Component c)
		{
			if (!Object.op_Implicit((Object)(object)c) || !modes.TryGetValue(Species(c), out ConfigEntry<SexMode> value))
			{
				return SexMode.Disabled;
			}
			Growup component = c.GetComponent<Growup>();
			Procreation val = ((Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.m_grownPrefab)) ? component.m_grownPrefab.GetComponent<Procreation>() : c.GetComponent<Procreation>());
			if (!Object.op_Implicit((Object)(object)val) || !((Behaviour)val).enabled || !Object.op_Implicit((Object)(object)val.m_offspring))
			{
				return SexMode.Disabled;
			}
			return value.Value;
		}

		internal static AnimalSex Read(Component c)
		{
			ZNetView val = (Object.op_Implicit((Object)(object)c) ? c.GetComponent<ZNetView>() : null);
			if (!Object.op_Implicit((Object)(object)val) || !val.IsValid())
			{
				return AnimalSex.Unknown;
			}
			return (AnimalSex)val.GetZDO().GetInt("zf_sex_v1", 0);
		}

		internal unsafe static void Ensure(Component c)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			if (modes.ContainsKey(Species(c)) && CreatureState.Owner(c, out ZDO zdo))
			{
				int num = zdo.GetInt("zf_sex_v1", 0);
				if (zdo.GetLong(ZDOVars.s_pregnant, 0L) != 0L && num != 2)
				{
					zdo.Set("zf_sex_v1", 2);
					ZDOID uid = zdo.m_uid;
					Plugin.Info("SEX migration existing pregnancy -> female, pregnancy/timers preserved ZDO=" + ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString());
				}
				else if (num != 1 && num != 2 && Mode(c) != SexMode.Disabled)
				{
					zdo.Set("zf_sex_v1", (int)BreedingMath.Assignment((AnimalSex)num, pregnant: false, Mode(c), Random.value));
					string[] obj = new string[6]
					{
						"SEX initial 50/50 assignment species=",
						Species(c),
						" ZDO=",
						null,
						null,
						null
					};
					ZDOID uid = zdo.m_uid;
					obj[3] = ((object)(*(ZDOID*)(&uid))/*cast due to .constrained prefix*/).ToString();
					obj[4] = " value=";
					obj[5] = zdo.GetInt("zf_sex_v1", 0).ToString();
					Plugin.Info(string.Concat(obj));
				}
			}
		}

		internal static void Tick()
		{
			MatingAuthority.Tick();
			if (!Plugin.ConfigReady || Time.realtimeSinceStartup < next)
			{
				return;
			}
			next = Time.realtimeSinceStartup + 1f;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				Ensure((Component)(object)allCharacter);
			}
		}

		internal static bool Eligible(Procreation p)
		{
			if (Object.op_Implicit((Object)(object)p) && !Object.op_Implicit((Object)(object)((Component)p).GetComponent<Growup>()) && Object.op_Implicit((Object)(object)((Component)p).GetComponent<Tameable>()) && ((Component)p).GetComponent<Character>().IsTamed() && p.ReadyForProcreation())
			{
				if (Object.op_Implicit((Object)(object)((Component)p).GetComponent<BaseAI>()))
				{
					return !((Component)p).GetComponent<BaseAI>().IsAlerted();
				}
				return true;
			}
			return false;
		}

		internal static Procreation? Partner(Procreation p)
		{
			SexMode mode = Mode((Component)(object)p);
			if (!Eligible(p) || !BreedingMath.CanCarry(mode, Read((Component)(object)p)))
			{
				return null;
			}
			string species = Species((Component)(object)p);
			return (from c in Character.GetAllCharacters()
				where (Object)(object)((Component)c).gameObject != (Object)(object)((Component)p).gameObject && Species((Component)(object)c) == species && Vector3.Distance(((Component)c).transform.position, ((Component)p).transform.position) <= p.m_partnerCheckRange
				select ((Component)c).GetComponent<Procreation>() into b
				where Object.op_Implicit((Object)(object)b) && Eligible(b)
				where BreedingMath.Compatible(mode, Read((Component)(object)p), Read((Component)(object)b), distinct: true)
				orderby Vector3.Distance(((Component)b).transform.position, ((Component)p).transform.position)
				select b).FirstOrDefault();
		}
	}
	[HarmonyPatch(typeof(Procreation), "Procreate")]
	internal static class SexPartnerSearch
	{
		[ThreadStatic]
		private static Procreation? scope;

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static void Prefix(Procreation __instance, out Procreation? __state)
		{
			__state = scope;
			scope = __instance;
			AnimalSexState.Ensure((Component)(object)__instance);
		}

		[HarmonyFinalizer]
		private static Exception? Finalizer(Exception? __exception, Procreation? __state)
		{
			scope = __state;
			return __exception;
		}

		internal static int Count(GameObject prefab, Vector3 centre, float range, bool events, bool ready)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			Procreation val = scope;
			if (ready && Object.op_Implicit((Object)(object)val) && AnimalSexState.Mode((Component)(object)val) != SexMode.Disabled && !Object.op_Implicit((Object)(object)((Component)val).GetComponent<Growup>()))
			{
				if (!Object.op_Implicit((Object)(object)AnimalSexState.Partner(val)))
				{
					return 0;
				}
				return 2;
			}
			return SpawnSystem.GetNrOfInstances(prefab, centre, range, events, ready);
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source)
		{
			MethodInfo original = AccessTools.Method(typeof(SpawnSystem), "GetNrOfInstances", new Type[5]
			{
				typeof(GameObject),
				typeof(Vector3),
				typeof(float),
				typeof(bool),
				typeof(bool)
			}, (Type[])null);
			MethodInfo replacement = AccessTools.Method(typeof(SexPartnerSearch), "Count", (Type[])null, (Type[])null);
			int replaced = 0;
			foreach (CodeInstruction item in source)
			{
				if (CodeInstructionExtensions.Calls(item, original))
				{
					item.operand = replacement;
					replaced++;
				}
				yield return item;
			}
			if (replaced != 4)
			{
				throw new InvalidOperationException("Native Procreate count contract changed: " + replaced);
			}
		}
	}
	[HarmonyPatch(typeof(Growup), "GrowUpdate")]
	internal static class PreserveAdultSex
	{
		[ThreadStatic]
		private static Growup? growing;

		[HarmonyPrefix]
		private static void Prefix(Growup __instance, out Growup? __state)
		{
			__state = growing;
			growing = __instance;
			AnimalSexState.Ensure((Component)(object)__instance);
		}

		[HarmonyFinalizer]
		private static Exception? Finalizer(Exception? __exception, Growup? __state)
		{
			growing = __state;
			return __exception;
		}

		private static GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(prefab, pos, rot);
			if (Object.op_Implicit((Object)(object)growing) && CreatureState.Owner((Component)(object)val.transform, out ZDO zdo))
			{
				AnimalSex animalSex = AnimalSexState.Read((Component)(object)growing);
				if (animalSex != AnimalSex.Unknown)
				{
					zdo.Set("zf_sex_v1", (int)animalSex);
				}
			}
			if (Object.op_Implicit((Object)(object)growing))
			{
				BearGenetics.Grown((Component)(object)growing, val);
			}
			Character component = val.GetComponent<Character>();
			if (Object.op_Implicit((Object)(object)component) && SexBody.Supported((Component)(object)component))
			{
				SexBody.Bind(component).Refresh();
				SexStats.Refresh(component);
			}
			return val;
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source)
		{
			int replaced = 0;
			foreach (CodeInstruction item in source)
			{
				if (item.operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(Object) && methodInfo.Name == "Instantiate" && methodInfo.IsGenericMethod && methodInfo.GetGenericArguments()[0] == typeof(GameObject) && methodInfo.GetParameters().Length == 3)
				{
					item.operand = AccessTools.Method(typeof(PreserveAdultSex), "Spawn", (Type[])null, (Type[])null);
					replaced++;
				}
				yield return item;
			}
			if (replaced != 1)
			{
				throw new InvalidOperationException("Growup spawn contract changed");
			}
		}
	}
	internal sealed class BearAppearance : MonoBehaviour
	{
		private string applied = "";

		private string failed = "";

		private readonly List<(SkinnedMeshRenderer Renderer, Mesh Mesh, Material[] Materials)> originals = new List<(SkinnedMeshRenderer, Mesh, Material[])>();

		private readonly List<Object> owned = new List<Object>();

		private static readonly Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>();

		internal static BearAppearance Bind(Character c)
		{
			return ((Component)c).GetComponent<BearAppearance>() ?? ((Component)c).gameObject.AddComponent<BearAppearance>();
		}

		internal void Refresh(BearGenes? genes)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			if (genes == null || genes.variant == applied || genes.variant == failed || (int)SystemInfo.graphicsDeviceType == 4)
			{
				return;
			}
			try
			{
				if (originals.Count == 0)
				{
					foreach (SkinnedMeshRenderer item in from val3 in ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true)
						where Object.op_Implicit((Object)(object)val3.sharedMesh) && ((Renderer)val3).sharedMaterials.Any((Material m) => Object.op_Implicit((Object)(object)m) && ((Object)m).name.StartsWith("Bjorn_mat", StringComparison.Ordinal))
						select val3)
					{
						originals.Add((item, item.sharedMesh, ((Renderer)item).sharedMaterials));
					}
				}
				if (originals.Count == 0)
				{
					return;
				}
				Restore();
				foreach (var original in originals)
				{
					var (r, _, _) = original;
					if (!Object.op_Implicit((Object)(object)r))
					{
						continue;
					}
					BearMesh bearMesh = BearMesh.Read(original.Mesh, r);
					Material[] array = ((IEnumerable<Material>)original.Materials).Select((Func<Material, Material>)((Material m) => new Material(m)
					{
						name = "ZF_Bjorn_" + genes.variant + "_" + ((Object)r).name
					})).ToArray();
					Material[] array2 = array;
					foreach (Material val in array2)
					{
						string key = ((Object)original.Mesh).GetInstanceID() + ":" + ((Object)val.mainTexture).GetInstanceID() + ":" + genes.variant;
						if (!textures.TryGetValue(key, out Texture2D value))
						{
							value = Paint(val.mainTexture, bearMesh, ((Object)r).name, genes.variant);
							textures[key] = value;
						}
						val.mainTexture = (Texture)(object)value;
						if (val.HasProperty("_EmissionMap"))
						{
							val.SetTexture("_EmissionMap", (Texture)null);
						}
						if (val.HasProperty("_EmissionColor"))
						{
							val.SetColor("_EmissionColor", Color.black);
						}
						if (val.HasProperty("_NoiseGlowEnabled"))
						{
							val.SetFloat("_NoiseGlowEnabled", 0f);
						}
						val.DisableKeyword("_EMISSION");
						owned.Add((Object)(object)val);
					}
					((Renderer)r).sharedMaterials = array;
					Mesh val2 = bearMesh.Create(original.Mesh, genes.variant, r);
					r.sharedMesh = val2;
					owned.Add((Object)(object)val2);
				}
				applied = genes.variant;
			}
			catch (Exception ex)
			{
				Restore();
				failed = genes.variant;
				Plugin.Error("BJORN appearance refused, native visual and gameplay retained: " + ex);
			}
		}

		private void Restore()
		{
			foreach (var original in originals)
			{
				if (Object.op_Implicit((Object)(object)original.Renderer))
				{
					original.Renderer.sharedMesh = original.Mesh;
					((Renderer)original.Renderer).sharedMaterials = original.Materials;
				}
			}
			foreach (Object item in owned)
			{
				if (Object.op_Implicit(item))
				{
					Object.Destroy(item);
				}
			}
			owned.Clear();
		}

		private void OnDestroy()
		{
			Restore();
		}

		internal static Texture2D Paint(Texture source, BearMesh geometry, string renderer, string variant)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_040d: Unknown result type (might be due to invalid IL or missing references)
			//IL_040f: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_0499: Unknown result type (might be due to invalid IL or missing references)
			//IL_049e: Unknown result type (might be due to invalid IL or missing references)
			RenderTexture active = RenderTexture.active;
			RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			Texture2D val = new Texture2D(source.width, source.height, (TextureFormat)4, true, false)
			{
				name = "ZF_Bjorn_" + variant + "_" + renderer,
				filterMode = (FilterMode)1,
				wrapMode = source.wrapMode
			};
			try
			{
				Graphics.Blit(source, temporary);
				RenderTexture.active = temporary;
				val.ReadPixels(new Rect(0f, 0f, (float)source.width, (float)source.height), 0, 0);
				val.Apply();
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
			Color[] pixels = val.GetPixels();
			bool[] array = geometry.Mask(source.width, source.height, upper: false);
			bool[] array2 = geometry.Mask(source.width, source.height, upper: true);
			bool flag = renderer == "Sphere";
			bool flag2 = renderer == "Asora" || renderer == "Plane";
			Color val2 = (Color)(variant switch
			{
				"black" => new Color(0.6f, 0.018f, 0.027f), 
				"brown" => new Color(0.34f, 0.46f, 0.1f), 
				"grizzly" => new Color(0.29f, 0.12f, 0.028f), 
				_ => new Color(0.1f, 0.4f, 0.72f), 
			});
			Color val4 = default(Color);
			Color val5 = default(Color);
			Color val7 = default(Color);
			for (int i = 0; i < pixels.Length; i++)
			{
				if (!array[i])
				{
					continue;
				}
				int num = i % source.width;
				int num2 = i / source.width;
				Color val3 = pixels[i];
				float num3 = val3.r * 0.2126f + val3.g * 0.7152f + val3.b * 0.0722f;
				if (flag)
				{
					float num4 = Vector2.Distance(new Vector2(((float)num + 0.5f) / (float)source.width, ((float)num2 + 0.5f) / (float)source.height), new Vector2(0.281f, 0.943f));
					if (num4 < 0.0115f)
					{
						((Color)(ref val3))..ctor(0.012f, 0.009f, 0.007f, val3.a);
					}
					else if (num4 < 0.06f)
					{
						float num5 = 0.8f + 0.2f * Mathf.Clamp01(num3 * 3f);
						((Color)(ref val3))..ctor(val2.r * num5, val2.g * num5, val2.b * num5, val3.a);
					}
				}
				else if (flag2 && num3 > 0.055f && num3 < 0.72f && (!(val3.r > val3.g * 1.7f) || !(val3.r > 0.35f)))
				{
					float num6 = Mathf.Clamp01(num3 * 2.8f);
					switch (variant)
					{
					case "black":
						((Color)(ref val4))..ctor(0.018f, 0.022f, 0.028f);
						((Color)(ref val5))..ctor(0.17f, 0.19f, 0.215f);
						break;
					case "gray":
						((Color)(ref val4))..ctor(0.045f, 0.055f, 0.065f);
						((Color)(ref val5))..ctor(0.34f, 0.35f, 0.33f);
						break;
					case "brown":
						((Color)(ref val4))..ctor(0.08f, 0.035f, 0.014f);
						((Color)(ref val5))..ctor(0.53f, 0.235f, 0.068f);
						break;
					default:
						((Color)(ref val4))..ctor(0.1f, 0.055f, 0.024f);
						((Color)(ref val5))..ctor(0.64f, 0.47f, 0.27f);
						break;
					}
					Color val6 = Color.Lerp(val4, val5, num6);
					if (variant == "gray")
					{
						((Color)(ref val7))..ctor(0.17f, 0.185f, 0.19f);
						val6 = ((num6 < 0.55f) ? Color.Lerp(val4, val7, num6 / 0.55f) : Color.Lerp(val7, val5, (num6 - 0.55f) / 0.45f));
					}
					if (variant == "grizzly" && array2[i])
					{
						int num7 = (num * 73856093) ^ (num2 * 19349663);
						if ((float)((uint)(num7 ^ (num7 >>> 13)) % 100u) / 100f > 0.48f)
						{
							val6 = Color.Lerp(val6, new Color(0.72f, 0.72f, 0.66f), 0.25f + 0.45f * num6);
						}
					}
					((Color)(ref val3))..ctor(val6.r, val6.g, val6.b, val3.a);
				}
				pixels[i] = val3;
			}
			val.SetPixels(pixels);
			val.Apply(true, true);
			return val;
		}
	}
	internal sealed class BearMesh
	{
		internal Vector3[] vertices = Array.Empty<Vector3>();

		internal Vector3[] normals = Array.Empty<Vector3>();

		internal Vector2[] uv = Array.Empty<Vector2>();

		internal BoneWeight[] weights = Array.Empty<BoneWeight>();

		internal int[] triangles = Array.Empty<int>();

		private Mesh baked;

		private static readonly Dictionary<int, BearMesh> cache = new Dictionary<int, BearMesh>();

		internal static BearMesh Read(Mesh native, SkinnedMeshRenderer renderer)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			if (cache.TryGetValue(((Object)native).GetInstanceID(), out BearMesh value))
			{
				return value;
			}
			BearMesh bearMesh = new BearMesh();
			bearMesh.baked = new Mesh();
			renderer.BakeMesh(bearMesh.baked, false);
			bearMesh.uv = bearMesh.baked.uv;
			bearMesh.triangles = bearMesh.baked.triangles;
			bearMesh.vertices = Attribute((VertexAttribute)0);
			bearMesh.normals = Attribute((VertexAttribute)1);
			bearMesh.weights = (BoneWeight[])(object)new BoneWeight[native.vertexCount];
			GraphicsBuffer boneWeightBuffer = native.GetBoneWeightBuffer((SkinWeights)4);
			try
			{
				boneWeightBuffer.GetData((Array)bearMesh.weights);
			}
			finally
			{
				((IDisposable)boneWeightBuffer)?.Dispose();
			}
			cache[((Object)native).GetInstanceID()] = bearMesh;
			return bearMesh;
			unsafe Vector3[] Attribute(VertexAttribute attribute)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: 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_0046: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				if ((int)native.GetVertexAttributeFormat(attribute) != 0 || native.GetVertexAttributeDimension(attribute) != 3)
				{
					throw new InvalidOperationException("Bjorn native vertex contract changed: " + ((object)(*(VertexAttribute*)(&attribute))/*cast due to .constrained prefix*/).ToString());
				}
				int vertexAttributeStream = native.GetVertexAttributeStream(attribute);
				int stride = native.GetVertexBufferStride(vertexAttributeStream);
				int offset = native.GetVertexAttributeOffset(attribute);
				byte[] bytes = new byte[native.vertexCount * stride];
				GraphicsBuffer vertexBuffer = native.GetVertexBuffer(vertexAttributeStream);
				try
				{
					vertexBuffer.GetData((Array)bytes);
				}
				finally
				{
					((IDisposable)vertexBuffer)?.Dispose();
				}
				return Enumerable.Range(0, native.vertexCount).Select((Func<int, Vector3>)((int i) => new Vector3(BitConverter.ToSingle(bytes, i * stride + offset), BitConverter.ToSingle(bytes, i * stride + offset + 4), BitConverter.ToSingle(bytes, i * stride + offset + 8)))).ToArray();
			}
		}

		internal Mesh Create(Mesh native, string variant, SkinnedMeshRenderer renderer)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			Mesh val = new Mesh
			{
				name = "ZF_Bjorn_" + variant + "_" + ((Object)native).name
			};
			Vector3[] array = (Vector3[])vertices.Clone();
			string[] array2 = renderer.bones.Select((Transform b) => (!Object.op_Implicit((Object)(object)b)) ? "" : ((Object)b).name).ToArray();
			float num = variant switch
			{
				"black" => -0.035f, 
				"brown" => 0.035f, 
				"grizzly" => 0.08f, 
				_ => -0.02f, 
			};
			Transform val2 = ((IEnumerable<Transform>)renderer.bones).FirstOrDefault((Func<Transform, bool>)((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "Head"));
			Vector3 val3;
			if (!Object.op_Implicit((Object)(object)val2))
			{
				Bounds bounds = native.bounds;
				val3 = ((Bounds)(ref bounds)).center;
			}
			else
			{
				val3 = ((Component)renderer).transform.InverseTransformPoint(val2.position);
			}
			Vector3 val4 = val3;
			for (int num2 = 0; num2 < array.Length; num2++)
			{
				BoneWeight val5 = weights[num2];
				float num3 = 0f;
				float num4 = 0f;
				(int, float)[] array3 = new(int, float)[4]
				{
					(((BoneWeight)(ref val5)).boneIndex0, ((BoneWeight)(ref val5)).weight0),
					(((BoneWeight)(ref val5)).boneIndex1, ((BoneWeight)(ref val5)).weight1),
					(((BoneWeight)(ref val5)).boneIndex2, ((BoneWeight)(ref val5)).weight2),
					(((BoneWeight)(ref val5)).boneIndex3, ((BoneWeight)(ref val5)).weight3)
				};
				for (int num5 = 0; num5 < array3.Length; num5++)
				{
					(int, float) tuple = array3[num5];
					if (tuple.Item1 < array2.Length)
					{
						if (new string[3] { "Head", "Nose", "Jaw" }.Contains(array2[tuple.Item1]))
						{
							num3 += tuple.Item2;
						}
						if (array2[tuple.Item1] == "Neck")
						{
							num4 += tuple.Item2;
						}
					}
				}
				array[num2].x *= 1f + num * num3 + ((variant == "grizzly") ? (0.045f * num4) : 0f);
				if (variant == "black")
				{
					array[num2].y += (array[num2].y - val4.y) * 0.025f * num3;
				}
				if (variant == "brown")
				{
					array[num2].z += (array[num2].z - val4.z) * 0.015f * num3;
				}
			}
			val.vertices = array;
			val.normals = normals;
			val.boneWeights = weights;
			val.bindposes = native.bindposes;
			for (int num6 = 0; num6 < 8; num6++)
			{
				List<Vector4> list = new List<Vector4>();
				baked.GetUVs(num6, list);
				if (list.Count == array.Length)
				{
					val.SetUVs(num6, list);
				}
			}
			if (baked.colors32.Length == array.Length)
			{
				val.colors32 = baked.colors32;
			}
			val.subMeshCount = baked.subMeshCount;
			for (int num7 = 0; num7 < baked.subMeshCount; num7++)
			{
				val.SetTriangles(baked.GetTriangles(num7), num7);
			}
			val.RecalculateNormals();
			val.RecalculateTangents();
			val.RecalculateBounds();
			return val;
		}

		internal bool[] Mask(int width, int height, bool upper)
		{
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: 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_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			bool[] array = new bool[width * height];
			float num = vertices.Max((Vector3 v) => v.z);
			float num2 = vertices.Min((Vector3 v) => v.z);
			Vector2 val4 = default(Vector2);
			for (int num3 = 0; num3 < triangles.Length; num3 += 3)
			{
				int num4 = triangles[num3];
				int num5 = triangles[num3 + 1];
				int num6 = triangles[num3 + 2];
				if (upper && (vertices[num4].z + vertices[num5].z + vertices[num6].z) / 3f < num2 + (num - num2) * 0.65f)
				{
					continue;
				}
				Vector2 val = uv[num4];
				Vector2 val2 = uv[num5];
				Vector2 val3 = uv[num6];
				int num7 = Mathf.Clamp(Mathf.FloorToInt(Mathf.Min(new float[3] { val.x, val2.x, val3.x }) * (float)width), 0, width - 1);
				int num8 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(new float[3] { val.x, val2.x, val3.x }) * (float)width), 0, width - 1);
				int num9 = Mathf.Clamp(Mathf.FloorToInt(Mathf.Min(new float[3] { val.y, val2.y, val3.y }) * (float)height), 0, height - 1);
				int num10 = Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(new float[3] { val.y, val2.y, val3.y }) * (float)height), 0, height - 1);
				float num11 = Cross(val2 - val, val3 - val);
				if (Mathf.Abs(num11) < 1E-10f)
				{
					continue;
				}
				for (int num12 = num9; num12 <= num10; num12++)
				{
					for (int num13 = num7; num13 <= num8; num13++)
					{
						((Vector2)(ref val4))..ctor(((float)num13 + 0.5f) / (float)width, ((float)num12 + 0.5f) / (float)height);
						float num14 = Cross(val2 - val4, val3 - val4) / num11;
						float num15 = Cross(val3 - val4, val - val4) / num11;
						float num16 = 1f - num14 - num15;
						if (num14 >= -0.02f && num15 >= -0.02f && num16 >= -0.02f)
						{
							array[num12 * width + num13] = true;
						}
					}
				}
			}
			return array;
			static float Cross(Vector2 p, Vector2 q)
			{
				//IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				return p.x * q.y - p.y * q.x;
			}
		}
	}
	internal sealed class BearDefense : MonoBehaviour
	{
		private delegate bool Patrol(BaseAI ai, out Vector3 point);

		private const string ThreatRpc = "ZF_BearThreat_v1";

		private const string Threat = "zf_guard_threat_v1";

		private const string Until = "zf_guard_until_v1";

		private const string Home = "zf_guard_home_v1";

		private static readonly FieldInfo Target = AccessTools.Field(typeof(MonsterAI), "m_targetCreature");

		private static readonly FieldInfo Static = AccessTools.Field(typeof(MonsterAI), "m_targetStatic");

		private static readonly FieldInfo WeaponTimer = AccessTools.Field(typeof(MonsterAI), "m_updateWeaponTimer");

		private static readonly Action<MonsterAI, bool> Alert = AccessTools.MethodDelegate<Action<MonsterAI, bool>>(AccessTools.Method(typeof(MonsterAI), "SetAlerted", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Action<MonsterAI> Wake = AccessTools.MethodDelegate<Action<MonsterAI>>(AccessTools.Method(typeof(MonsterAI), "Wakeup", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Patrol GetPatrol = AccessTools.MethodDelegate<Patrol>(AccessTools.Method(typeof(BaseAI), "GetPatrolPoint", (Type[])null, (Type[])null), (object)null, true);

		private Character animal;

		private MonsterAI ai;

		private ZNetView view;

		private string reason = "initialisation";

		private string lastTrace = "";

		private float nextScan;

		private float nextTrace;

		private bool Owned
		{
			get
			{
				ZDO zdo;
				if (Plugin.ConfigReady && Applies(animal) && !animal.IsDead() && Object.op_Implicit((Object)(object)ai))
				{
					return CreatureState.Owner((Component)(object)animal, out zdo);
				}
				return false;
			}
		}

		private bool Ridden
		{
			get
			{
				if (Object.op_Implicit((Object)(object)((Component)animal).GetComponent<Tameable>()?.m_saddle))
				{
					return ((Component)animal).GetComponent<Tameable>().m_saddle.HaveValidUser();
				}
				return false;
			}
		}

		internal static bool Applies(Character c)
		{
			if (Object.op_Implicit((Object)(object)c) && c.IsTamed() && CreatureState.Is((Component)(object)c, "Bjorn"))
			{
				return !Object.op_Implicit((Object)(object)((Component)c).GetComponent<Growup>());
			}
			return false;
		}

		internal static bool Enemy(Character bear, Character other)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)other) || (Object)(object)other == (Object)(object)bear)
			{
				return false;
			}
			return DefenseRules.Hostile(((object)other.GetFaction()/*cast due to .constrained prefix*/).ToString(), bear.GetGroup().Length > 0 && bear.GetGroup() == other.GetGroup(), other is Player, other.IsTamed(), other.IsDead(), other.m_aiSkipTarget, Object.op_Implicit((Object)(object)other.GetBaseAI()) && other.GetBaseAI().IsAggravated());
		}

		internal static BearDefense Bind(Character c)
		{
			BearDefense bearDefense = ((Component)c).GetComponent<BearDefense>();
			if (!Object.op_Implicit((Object)(object)bearDefense))
			{
				bearDefense = ((Component)c).gameObject.AddComponent<BearDefense>();
			}
			if (!Object.op_Implicit((Object)(object)bearDefense.view))
			{
				bearDefense.animal = c;
				bearDefense.ai = ((Component)c).GetComponent<MonsterAI>();
				bearDefense.view = ((Component)c).GetComponent<ZNetView>();
				bearDefense.view.Register<ZDOID, ZDOID>("ZF_BearThreat_v1", (Action<long, ZDOID, ZDOID>)bearDefense.Receive);
			}
			return bearDefense;
		}

		private Vector3 Centre()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			GameObject followTarget = ai.GetFollowTarget();
			if (Object.op_Implicit((Object)(object)followTarget))
			{
				return followTarget.transform.position;
			}
			if (GetPatrol((BaseAI)(object)ai, out var point))
			{
				return point;
			}
			ZDO zDO = view.GetZDO();
			if (!zDO.GetBool("zf_guard_home_v1_set", false))
			{
				zDO.Set("zf_guard_home_v1", ((Component)animal).transform.position);
				zDO.Set("zf_guard_home_v1_set", true);
			}
			return zDO.GetVec3("zf_guard_home_v1", ((Component)animal).transform.position);
		}

		private bool InGuard(Character c)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0028: Unknown result type (might be due to invalid IL or missing references)
			return DefenseRules.Within(Vector3.Distance(Centre(), ((Component)c).transform.position), Vector3.Distance(Centre(), ((Component)animal).transform.position), Plugin.GuardRadius.Value);
		}

		private bool Allowed(Character c, bool selfHit = false)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			if (!Enemy(animal, c))
			{
				return false;
			}
			if (InGuard(c))
			{
				return true;
			}
			long ms;
			bool num = selfHit || (ServerClock.TryNow(out ms) && view.GetZDO().GetLong("zf_guard_until_v1", 0L) > ms && view.GetZDO().GetZDOID("zf_guard_threat_v1") == c.GetZDOID());
			Character obj = animal;
			Character obj2 = ((obj is Humanoid) ? obj : null);
			float nativeReach = ((obj2 == null) ? ((float?)null) : ((Humanoid)obj2).GetCurrentWeapon()?.m_shared.m_aiAttackRange) ?? animal.GetRadius();
			if (num)
			{
				return DefenseRules.CloseRetaliation(Vector3.Distance(((Component)animal).transform.position, ((Component)c).transform.position), nativeReach, c.GetRadius());
			}
			return false;
		}

		private bool Protects(Character victim)
		{
			//IL_001e: 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)
			if ((Object)(object)victim == (Object)(object)animal)
			{
				return true;
			}
			if (!(victim is Player) || Vector3.Distance(((Component)victim).transform.position, Centre()) > Plugin.GuardRadius.Value)
			{
				return false;
			}
			GameObject followTarget = ai.GetFollowTarget();
			if (Object.op_Implicit((Object)(object)followTarget))
			{
				return (Object)(object)followTarget == (Object)(object)((Component)victim).gameObject;
			}
			return true;
		}

		private void Receive(long sender, ZDOID victimId, ZDOID attackerId)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (Owned && !Ridden)
			{
				GameObject val = ZNetScene.instance.FindInstance(victimId);
				GameObject val2 = ZNetScene.instance.FindInstance(attackerId);
				Character val3 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<Character>() : null);
				Character val4 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent<Character>() : null);
				ZNetView val5 = (Object.op_Implicit((Object)(object)val3) ? ((Component)val3).GetComponent<ZNetView>() : null);
				if (!Object.op_Implicit((Object)(object)val5) || !val5.IsValid() || val5.GetZDO().GetOwner() != sender || !Protects(val3) || !Allowed(val4, (Object)(object)val3 == (Object)(object)animal))
				{
					reason = "notification refusée : autorité, allié ou rayon / notification rejected: authority, ally or radius";
				}
				else
				{
					Remember(val4, "agression reçue du pair autoritaire de la victime / hit reported by victim authority");
				}
			}
		}

		internal static void Damage(Character victim, Character attacker)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)attacker) || !CreatureState.Owner((Component)(object)victim, out ZDO _) || !Object.op_Implicit((Object)(object)ZNetScene.instance))
			{
				return;
			}
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (!Applies(allCharacter) || Vector3.Distance(((Component)allCharacter).transform.position, ((Component)victim).transform.position) > 60f || !Enemy(allCharacter, attacker))
				{
					continue;
				}
				BearDefense bearDefense = Bind(allCharacter);
				if (Object.op_Implicit((Object)(object)bearDefense.view) && bearDefense.view.IsValid())
				{
					if (bearDefense.view.IsOwner())
					{
						bearDefense.Receive(ZDOMan.GetSessionID(), victim.GetZDOID(), attacker.GetZDOID());
						continue;
					}
					bearDefense.view.InvokeRPC(bearDefense.view.GetZDO().GetOwner(), "ZF_BearThreat_v1", new object[2]
					{
						victim.GetZDOID(),
						attacker.GetZDOID()
					});
				}
			}
		}

		private void Remember(Character target, string why)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (ServerClock.TryNow(out var ms))
			{
				ZDO zDO = view.GetZDO();
				zDO.Set("zf_guard_threat_v1", target.GetZDOID());
				zDO.Set("zf_guard_until_v1", ms + 12000);
				reason = why;
				Alert(ai, arg2: true);
				Wake(ai);
				Target.SetValue(ai, target);
				Static.SetValue(ai, null);
				WeaponTimer.SetValue(ai, 0f);
			}
		}

		internal void Prepare()
		{
			if (!Owned || Ridden || !(Time.time >= nextScan))
			{
				return;
			}
			nextScan = Time.time + 0.5f;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (Enemy(animal, allCharacter) && InGuard(allCharacter))
				{
					MonsterAI component = ((Component)allCharacter).GetComponent<MonsterAI>();
					Character val = ((component != null) ? ((BaseAI)component).GetTargetCreature() : null);
					if (Object.op_Implicit((Object)(object)val) && Protects(val) && allCharacter.GetBaseAI().IsAlerted())
					{
						Remember(allCharacter, "menace visant le joueur protégé ou l’ours / threat targets protected player or bear");
						break;
					}
				}
			}
		}

		internal void AfterTarget(ref bool canHear, ref bool canSee)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			if (!Owned)
			{
				return;
			}
			if (Ridden)
			{
				Target.SetValue(ai, null);
				Static.SetValue(ai, null);
				reason = "cavalier : commandes conservées / rider controls";
				return;
			}
			if (ServerClock.TryNow(out var ms) && view.GetZDO().GetLong("zf_guard_until_v1", 0L) > ms)
			{
				GameObject val = ZNetScene.instance.FindInstance(view.GetZDO().GetZDOID("zf_guard_threat_v1"));
				Character val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<Character>() : null);
				if (Object.op_Implicit((Object)(object)val2) && Allowed(val2))
				{
					Target.SetValue(ai, val2);
				}
			}
			Character targetCreature = ((BaseAI)ai).GetTargetCreature();
			if (Object.op_Implicit((Object)(object)targetCreature) && !Allowed(targetCreature))
			{
				Target.SetValue(ai, null);
				Static.SetValue(ai, null);
				canHear = (canSee = false);
				Alert(ai, arg2: false);
				reason = "cible rejetée : allié, morte ou hors périmètre / ally, dead or outside guard radius";
			}
			else if (Object.op_Implicit((Object)(object)targetCreature))
			{
				canHear = ((BaseAI)ai).CanHearTarget(targetCreature);
				canSee = ((BaseAI)ai).CanSeeTarget(targetCreature);
				if (canHear | canSee)
				{
					Alert(ai, arg2: true);
				}
				if (view.GetZDO().GetZDOID("zf_guard_threat_v1") != targetCreature.GetZDOID())
				{
					reason = "perception native d’une cible hostile / native hostile perception";
				}
			}
			else
			{
				reason = "aucune menace perçue, retour Suivre/Rester / no sensed threat, follow/stay";
			}
			Trace();
		}

		private void Trace()
		{
			if (Plugin.AiTrace.Value && !(Time.time < nextTrace))
			{
				nextTrace = Time.time + 2f;
				string text = Describe(animal);
				if (text != lastTrace)
				{
					lastTrace = text;
					Plugin.Info("DEFENSE " + text);
				}
			}
		}

		internal static string Describe(Character c)
		{
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			BearDefense component = ((Component)c).GetComponent<BearDefense>();
			MonsterAI component2 = ((Component)c).GetComponent<MonsterAI>();
			ZNetView component3 = ((Component)c).GetComponent<ZNetView>();
			Character val = (Object.op_Implicit((Object)(object)component2) ? ((BaseAI)component2).GetTargetCreature() : null);
			Humanoid val2 = (Humanoid)(object)((c is Humanoid) ? c : null);
			ItemData val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetCurrentWeapon() : null);
			string text = ((!Object.op_Implicit((Object)(object)component3) || !component3.IsValid()) ? "ZDO invalide / invalid ZDO" : ((!component3.IsOwner()) ? "relevé non autoritaire / not authority" : ((!Applies(c)) ? "hors périmètre / excluded" : (c.HaveRider() ? "cavalier / rider" : ((!Object.op_Implicit((Object)(object)val)) ? "aucune cible / no target" : ((val3 == null) ? "arme native absente / no native weapon" : (c.InAttack() ? "attaque en cours / attacking" : (c.IsStaggering() ? "étourdi / staggered" : (c.IsKnockedBack() ? "projection / knocked back" : ((Object.op_Implicit((Object)(object)component2) && !((BaseAI)component2).CanSeeTarget(val)) ? "ligne de vue bloquée / no line of sight" : ((Vector3.Distance(((Component)c).transform.position, ((Component)val).transform.position) - val.GetRadius() > val3.m_shared.m_aiAttackRange) ? "approche, hors portée / approaching" : ((Time.time - val3.m_lastAttackTime <= val3.m_shared.m_aiAttackInterval) ? "recharge native / native cooldown" : ((Object.op_Implicit((Object)(object)component2) && !((BaseAI)component2).CanUseAttack(val3)) ? "conditions de l’arme native / native weapon conditions" : ((Object.op_Implicit((Object)(object)component2) && !((BaseAI)component2).IsLookingAt(((Component)val).transform.position, val3.m_shared.m_aiAttackMaxAngle, val3.m_shared.m_aiInvertAngleCheck)) ? "angle natif / native facing angle" : ((c.GetTimeSinceLastAttack() < (float)AccessTools.Field(typeof(MonsterAI), "m_minAttackInterval").GetValue(component2)) ? "délai global natif / native global cooldown" : "prêt, traitement natif / ready for native processing")))))))))))))));
			object[] obj = new object[24]
			{
				c.GetHoverName(),
				c.GetZDOID(),
				c.IsTamed(),
				c.GetFaction(),
				c.GetGroup(),
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null,
				null
			};
			long? obj2;
			if (component3 == null)
			{
				obj2 = null;
			}
			else
			{
				ZDO zDO = component3.GetZDO();
				obj2 = ((zDO != null) ? new long?(zDO.GetOwner()) : ((long?)null));
			}
			obj[5] = obj2;
			obj[6] = Object.op_Implicit((Object)(object)component3) && component3.IsValid() && component3.IsOwner();
			object obj3;
			if (component2 == null)
			{
				obj3 = null;
			}
			else
			{
				GameObject followTarget = component2.GetFollowTarget();
				obj3 = ((followTarget != null) ? ((Object)followTarget).name : null);
			}
			obj[7] = obj3;
			obj[8] = ((val != null) ? new ZDOID?(val.GetZDOID()) : ((ZDOID?)null));
			obj[9] = component?.reason ?? "pas encore exécuté / not run yet";
			obj[10] = text;
			obj[11] = ((object)component2)?.GetType().Name;
			obj[12] = ((Character)(val2?)).m_aiCannotTargetOthers;
			obj[13] = c.m_aiSkipTarget;
			obj[14] = component2?.m_fleeIfNotAlerted;
			obj[15] = component2?.m_fleeIfLowHealth;
			obj[16] = component2?.m_fleeIfHurtWhenTargetCantBeReached;
			obj[17] = ((BaseAI)(component2?)).m_afraidOfFire;
			obj[18] = ((BaseAI)(component2?)).m_avoidFire;
			obj[19] = component2?.m_alertRange;
			obj[20] = Plugin.GuardRadius.Value;
			obj[21] = val3?.m_shared.m_name;
			obj[22] = val3?.m_shared.m_aiAttackRange;
			obj[23] = val3?.m_shared.m_aiAttackInterval;
			return string.Format("{0} ZDO={1} tame={2} faction={3} group={4} owner={5} localAuthority={6} follow={7} target={8} reason={9} attackGate={10} ai={11} cannotTarget={12} skip={13} fear={14}/{15}/{16} fire={17}/{18} nativeAlertRange={19} guard={20}m weapon={21} range={22} interval={23}", obj);
		}
	}
	[HarmonyPatch(typeof(BaseAI), "IsEnemy", new Type[]
	{
		typeof(Character),
		typeof(Character)
	})]
	internal static class BearHostility
	{
		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(Character a, Character b, ref bool __result)
		{
			if (BearDefense.Applies(a))
			{
				__result = BearDefense.Enemy(a, b);
			}
			else if (BearDefense.Applies(b))
			{
				__result = BearDefense.Enemy(b, a);
			}
		}
	}
	[HarmonyPatch(typeof(MonsterAI), "UpdateAI")]
	internal static class BearGuardAI
	{
		internal sealed class Snapshot
		{
			internal float Range;

			internal float Low;

			internal bool NotAlerted;

			internal bool Unreachable;
		}

		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static void Prefix(MonsterAI __instance, out Snapshot? __state)
		{
			__state = null;
			Character component = ((Component)__instance).GetComponent<Character>();
			if (Plugin.ConfigReady && BearDefense.Applies(component) && CreatureState.Owner((Component)(object)component, out ZDO _))
			{
				BearDefense.Bind(component).Prepare();
				if (!component.HaveRider())
				{
					__state = new Snapshot
					{
						Range = __instance.m_alertRange,
						Low = __instance.m_fleeIfLowHealth,
						NotAlerted = __instance.m_fleeIfNotAlerted,
						Unreachable = __instance.m_fleeIfHurtWhenTargetCantBeReached
					};
					__instance.m_alertRange = Plugin.GuardRadius.Value;
					__instance.m_fleeIfNotAlerted = false;
					__instance.m_fleeIfLowHealth = 0f;
					__instance.m_fleeIfHurtWhenTargetCantBeReached = false;
				}
			}
		}

		[HarmonyFinalizer]
		private static Exception? Finalizer(MonsterAI __instance, Snapshot? __state, Exception? __exception)
		{
			if (__state != null)
			{
				__instance.m_alertRange = __state.Range;
				__instance.m_fleeIfLowHealth = __state.Low;
				__instance.m_fleeIfNotAlerted = __state.NotAlerted;
				__instance.m_fleeIfHurtWhenTargetCantBeReached = __state.Unreachable;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(MonsterAI), "UpdateTarget")]
	internal static class BearGuardTarget
	{
		[HarmonyPostfix]
		private static void Postfix(MonsterAI __instance, ref bool canHearTarget, ref bool canSeeTarget)
		{
			Character component = ((Component)__instance).GetComponent<Character>();
			if (BearDefense.Applies(component) && CreatureState.Owner((Component)(object)component, out ZDO _))
			{
				BearDefense.Bind(component).AfterTarget(ref canHearTarget, ref canSeeTarget);
			}
		}
	}
	[HarmonyPatch(typeof(MonsterAI), "SetTarget")]
	internal static class BearRejectFriendlyHit
	{
		[HarmonyPrefix]
		private static bool Prefix(MonsterAI __instance, Character attacker)
		{
			Character component = ((Component)__instance).GetComponent<Character>();
			if (BearDefense.Applies(component))
			{
				return BearDefense.Enemy(component, attacker);
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Character), "RPC_Damage")]
	internal static class BearDamageNotification
	{
		[HarmonyPrefix]
		private static void Prefix(Character __instance, out float __state)
		{
			__state = __instance.GetHealth();
		}

		[HarmonyPostfix]
		private static void Postfix(Character __instance, HitData hit, float __state)
		{
			if (__instance.GetHealth() < __state && CreatureState.Owner((Component)(object)__instance, out ZDO _))
			{
				BearDefense.Damage(__instance, hit.GetAttacker());
			}
		}
	}
	[HarmonyPatch(typeof(BaseAI), "Follow")]
	internal static class BearFollow
	{
		private sealed class State
		{
			internal GameObject? Target;

			internal bool Stopped;

			internal float Stop;
		}

		private static readonly ConditionalWeakTable<BaseAI, State> States = new ConditionalWeakTable<BaseAI, State>();

		private static readonly Func<BaseAI, float, Vector3, float, bool, bool> Move = AccessTools.MethodDelegate<Func<BaseAI, float, Vector3, float, bool, bool>>(AccessTools.Method(typeof(BaseAI), "MoveTo", (Type[])null, (Type[])null), (object)null, true);

		internal static float Support(Character body, Vector3 direction)
		{
			//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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			CapsuleCollider component = ((Component)body).GetComponent<CapsuleCollider>();
			if (!Object.op_Implicit((Object)(object)component) || !((Collider)component).enabled)
			{
				return body.GetRadius();
			}
			Bounds bounds = ((Collider)component).bounds;
			return Mathf.Max(0f, Vector3.Dot(((Bounds)(ref bounds)).center - ((Component)body).transform.position, direction) + Mathf.Abs(direction.x) * ((Bounds)(ref bounds)).extents.x + Mathf.Abs(direction.z) * ((Bounds)(ref bounds)).extents.z);
		}

		internal static float Clearance(Character bear, Character player, Vector3 dir)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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)
			return Mathf.Max(3f, Support(bear, dir) + Support(player, -dir) + ((Utils.GetPrefabName(((Component)bear).gameObject) == "Lox") ? Plugin.LoxFollowGap.Value : Plugin.FollowGap.Value));
		}

		[HarmonyPrefix]
		private static bool Prefix(BaseAI __instance, GameObject go, float dt)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			Character component = ((Component)__instance).GetComponent<Character>();
			Player val = (Object.op_Implicit((Object)(object)go) ? go.GetComponent<Player>() : null);
			if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)val) || !MountCapabilities.Supported(component) || !component.IsTamed() || !Plugin.ConfigReady || !CreatureState.Owner((Component)(object)__instance, out ZDO _))
			{
				return true;
			}
			Sadle saddle = ((Component)component).GetComponent<Tameable>().m_saddle;
			if (Object.op_Implicit((Object)(object)saddle) && saddle.HaveValidUser())
			{
				__instance.StopMoving();
				return false;
			}
			Vector3 val2 = ((Component)val).transform.position - ((Component)component).transform.position;
			val2.y = 0f;
			Vector3 val3 = ((((Vector3)(ref val2)).sqrMagnitude > 0f) ? ((Vector3)(ref val2)).normalized : ((Component)component).transform.forward);
			float num = Clearance(component, (Character)(object)val, val3);
			State value = States.GetValue(__instance, (BaseAI _) => new State());
			if ((Object)(object)value.Target != (Object)(object)go)
			{
				value.Target = go;
				value.Stopped = false;
			}
			float num2 = (value.Stopped ? 0f : (Mathf.Max(0f, Vector3.Dot(component.GetVelocity(), val3)) * 0.35f));
			num += num2;
			if (value.Stopped)
			{
				num = Mathf.Max(num, value.Stop);
			}
			value.Stopped = MovementMath.ShouldStop(value.Stopped, ((Vector3)(ref val2)).magnitude, num, Plugin.FollowResume.Value);
			if (value.Stopped)
			{
				value.Stop = num;
				__instance.StopMoving();
				component.SetRun(false);
			}
			else
			{
				value.Stop = num;
				bool arg = ((Vector3)(ref val2)).magnitude > Mathf.Max(10f, num + 4f);
				Move(__instance, dt, ((Component)val).transform.position, num, arg);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(MonsterAI), "UpdateConsumeItem")]
	internal static class BearFood
	{
		[ThreadStatic]
		internal static MonsterAI? Consumer;

		internal static bool GroundFood(ItemDrop item)
		{
			Fish component = ((Component)item).GetComponent<Fish>();
			if (Object.op_Implicit((Object)(object)component))
			{
				if (item.m_itemData.m_pickedUp)
				{
					return component.IsOutOfWater();
				}
				return false;
			}
			return true;
		}

		[HarmonyPrefix]
		[HarmonyPriority(0)]
		private static void Prefix(MonsterAI __instance, out MonsterAI? __state)
		{
			__state = Consumer;
			Consumer = (CreatureState.Is((Component)(object)__instance, "Bjorn") ? __instance : null);
			if (Object.op_Implicit((Object)(object)Consumer))
			{
				Tameable component = ((Component)__instance).GetComponent<Tameable>();
				if (Object.op_Implicit((Object)(object)component))
				{
					Policy.RefreshBear(component);
				}
				Traverse<ItemDrop> val = Traverse.Create((object)__instance).Field<ItemDrop>("m_consumeTarget");
				if (Object.op_Implicit((Object)(object)val.Value) && !GroundFood(val.Value))
				{
					val.Value = null;
				}
			}
		}

		[HarmonyFinalizer]
		private static void Finalizer(MonsterAI? __state)
		{
			Consumer = __state;
		}
	}
	[HarmonyPatch(typeof(MonsterAI), "FindClosestConsumableItem")]
	internal static class BearFishSelection
	{
		[ThreadStatic]
		internal static HashSet<ItemData>? Excluded;

		[HarmonyPrefix]
		private static void Prefix(MonsterAI __instance, float maxRange, out HashSet<ItemData>? __state)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			__state = Excluded;
			if (!CreatureState.Is((Component)(object)__instance, "Bjorn"))
			{
				return;
			}
			Excluded = new HashSet<ItemData>();
			Collider[] array = Physics.OverlapSphere(((Component)__instance).transform.position, maxRange, LayerMask.GetMask(new string[1] { "item" }));
			foreach (Collider val in array)
			{
				ItemDrop val2 = (Object.op_Implicit((Object)(object)val.attachedRigidbody) ? ((Component)val.attachedRigidbody).GetComponent<ItemDrop>() : null);
				if (Object.op_Implicit((Object)(object)val2) && !BearFood.GroundFood(val2))
				{
					Excluded.Add(val2.m_itemData);
				}
			}
		}

		[HarmonyFinalizer]
		private static void Finalizer(HashSet<ItemData>? __state)
		{
			Excluded = __state;
		}

		[HarmonyPostfix]
		private static void Postfix(MonsterAI __instance, ref ItemDrop __result)
		{
			if (CreatureState.Is((Component)(object)__instance, "Bjorn") && Object.op_Implicit((Object)(object)__result) && !BearFood.GroundFood(__result))
			{
				__result = null;
			}
		}
	}
	[HarmonyPatch(typeof(MonsterAI), "CanConsume")]
	internal static class BearFishCandidate
	{
		[HarmonyPostfix]
		private static void Postfix(MonsterAI __instance, ItemData item, ref bool __result)
		{
			if (__result && CreatureState.Is((Component)(object)__instance, "Bjorn"))
			{
				HashSet<ItemData>? excluded = BearFishSelection.Excluded;
				if (excluded != null && excluded.Contains(item))
				{
					__result = false;
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "RemoveOne")]
	internal static class BearMealAudit
	{
		[HarmonyPrefix]
		private static bool Prefix(ItemDrop __instance, out int __state, ref bool __result)
		{
			__state = (Object.op_Implicit((Object)(object)BearFood.Consumer) ? __instance.m_itemData.m_stack : (-1));
			if (__state < 0 || BearFood.GroundFood(__instance))
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPostfix]
		private static void Postfix(ItemDrop __instance, int __state, bool __result)
		{
			if (__state >= 0 && __result)
			{
				int num = ((__state != 1) ? __instance.m_itemData.m_stack : 0);
				string message = $"BJORN FOOD UNIT prefab={Utils.GetPrefabName(((Component)__instance).gameObject)} quality={__instance.m_itemData.m_quality} before={__state} after={num} removed={__state - num} nativeRemoveOne=true";
				if (__state - num != 1)
				{
					Plugin.Error(message);
				}
				else
				{
					Plugin.Info(message);
				}
			}
		}
	}
	[DataContract]
	internal sealed class Ancestor
	{
		[DataMember]
		public string id = "";

		[DataMember]
		public string variant = "";

		internal Ancestor Copy()
		{
			return new Ancestor
			{
				id = id,
				variant = variant
			};
		}
	}
	[DataContract]
	internal sealed class BearGenes
	{
		[DataMember]
		public int schema = 1;

		[DataMember]
		public string id = "";

		[DataMember]
		public string variant = "";

		[DataMember]
		public string origin = "";

		[DataMember]
		public Ancestor[] g1 = BearInheritance.Unknown(2);

		[DataMember]
		public Ancestor[] g2 = BearInheritance.Unknown(4);

		[DataMember]
		public Ancestor[] g3 = BearInheritance.Unknown(8);

		[DataMember]
		public double[] birth = Array.Empty<double>();

		[DataMember]
		public double[] weights = Array.Empty<double>();

		[DataMember]
		public string seed = "";

		[DataMember]
		public long conceptionToken;
	}
	internal static class BearInheritance
	{
		internal static readonly string[] Variants = new string[4] { "grizzly", "brown", "black", "gray" };

		internal static readonly double[] DefaultWeights = new double[3] { 0.5, 0.3, 0.2 };

		internal static readonly double[] DefaultFoundation = new double[4] { 0.25, 0.25, 0.25, 0.25 };

		internal static bool Known(string v)
		{
			return Array.IndexOf(Variants, v) >= 0;
		}

		internal static bool Finite(double d)
		{
			if (!double.IsNaN(d))
			{
				return !double.IsInfinity(d);
			}
			return false;
		}

		internal static double[] Normalize(double[] values, int count)
		{
			if (values == null || values.Length != count || values.Any((double d) => !Finite(d) || d < 0.0))
			{
				throw new ArgumentException("Negative/non-finite genetic weight");
			}
			double max = values.Max();
			if (max <= 0.0)
			{
				throw new ArgumentException("All genetic weights are zero");
			}
			double sum = values.Sum((double d) => d / max);
			return values.Select((double d) => d / max / sum).ToArray();
		}

		internal static Ancestor[] Unknown(int count)
		{
			return (from _ in Enumerable.Range(0, count)
				select new Ancestor()).ToArray();
		}

		private static bool Level(Ancestor[] a, int max)
		{
			if (a != null && a.Length <= max)
			{
				return a.All((Ancestor p) => p != null && p.id != null && p.id.Length <= 128 && p.variant != null && ((p.id.Length == 0 && p.variant.Length == 0) || (p.id.Length > 0 && Known(p.variant))));
			}
			return false;
		}

		internal static bool Valid(BearGenes? b)
		{
			if (b != null && b.schema == 1 && !string.IsNullOrEmpty(b.id) && b.id.Length <= 128 && Known(b.variant) && Level(b.g1, 2) && Level(b.g2, 4) && Level(b.g3, 8) && b.seed != null && b.seed.Length <= 128 && b.origin != null && b.birth != null && (b.birth.Length == 0 || (b.birth.Length == 4 && b.birth.All((double p) => Finite(p) && p >= 0.0 && p <= 1.0) && Math.Abs(b.birth.Sum() - 1.0) < 1E-08)) && b.weights != null)
			{
				if (b.weights.Length != 0)
				{
					if (b.weights.Length == 3 && b.weights.All((double p) => Finite(p) && p >= 0.0))
					{
						return b.weights.Any((double p) => p > 0.0);
					}
					return false;
				}
				return true;
			}
			return false;
		}

		private static Ancestor Self(BearGenes? b)
		{
			if (!Valid(b))
			{
				return new Ancestor();
			}
			return new Ancestor
			{
				id = b.id,
				variant = b.variant
			};
		}

		private static Ancestor[] Pad(Ancestor[]? a, int count)
		{
			return (from i in Enumerable.Range(0, count)
				select (a == null || i >= a.Length) ? new Ancestor() : a[i].Copy()).ToArray();
		}

		internal static BearGenes Child(BearGenes? a, BearGenes? b, string id)
		{
			BearGenes bearGenes = new BearGenes();
			bearGenes.id = id;
			bearGenes.origin = "inherited";
			bearGenes.g1 = new Ancestor[2]
			{
				Self(a),
				Self(b)
			};
			bearGenes.g2 = Pad(a?.g1, 2).Concat(Pad(b?.g1, 2)).ToArray();
			bearGenes.g3 = Pad(a?.g2, 4).Concat(Pad(b?.g2, 4)).ToArray();
			return bearGenes;
		}

		internal static double[] Probabilities(BearGenes child, double[] weights)
		{
			double[] array = Normalize(weights, 3);
			double[] array2 = new double[4];
			Ancestor[][] array3 = new Ancestor[3][] { child.g1, child.g2, child.g3 };
			int[] array4 = new int[3] { 2, 4, 8 };
			for (int i = 0; i < 3; i++)
			{
				if (!Level(array3[i], array4[i]))
				{
					throw new ArgumentException("Unbounded or invalid genetic snapshots");
				}
				Ancestor[] array5 = array3[i];
				foreach (Ancestor ancestor in array5)
				{
					int num = Array.IndexOf(Variants, ancestor.variant);
					if (num >= 0)
					{
						array2[num] += array[i] / (double)array4[i];
					}
				}
			}
			if (array2.All((double d) => d == 0.0))
			{
				throw new ArgumentException("No weighted known ancestry; foundation required");
			}
			return Normalize(array2, 4);
		}

		internal static double Roll(string seed)
		{
			using SHA256 sHA = SHA256.Create();
			byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(seed));
			ulong num = 0uL;
			for (int i = 0; i < 8; i++)
			{
				num = (num << 8) | array[i];
			}
			return (double)(num >> 11) * 1.1102230246251565E-16;
		}

		internal static string Draw(double[] probabilities, string seed)
		{
			double[] array = Normalize(probabilities, 4);
			double num = Roll(seed);
			double num2 = 0.0;
			int num3 = 0;
			for (int i = 0; i < 4; i++)
			{
				if (array[i] > 0.0)
				{
					num3 = i;
				}
				num2 += array[i];
				if (num < num2)
				{
					return Variants[i];
				}
			}
			return Variants[num3];
		}

		internal static BearGenes Complete(BearGenes child, double[] probabilities, double[] weights, string seed)
		{
			child.birth = Normalize(probabilities, 4);
			child.weights = (double[])weights.Clone();
			child.seed = seed;
			child.variant = Draw(child.birth, seed);
			return child;
		}

		internal static double[] Percentages(double[] p)
		{
			double[] n = Normalize(p, 4);
			int[] units = n.Select((double x) => (int)Math.Floor(x * 1000.0)).ToArray();
			int count = 1000 - units.Sum();
			foreach (int item in (from i in Enumerable.Range(0, 4)
				orderby n[i] * 1000.0 - (double)units[i] descending, i
				select i).Take(count))
			{
				units[item]++;
			}
			return units.Select((int x) => (double)x / 10.0).ToArray();
		}
	}
	internal static class SexScaleMath
	{
		internal static double Factor(bool male, bool hermaphrodite, double maturity, double adultFactor)
		{
			if (!male || hermaphrodite)
			{
				return 1.0;
			}
			if (!BearInheritance.Finite(adultFactor) || adultFactor < 1.0 || adultFactor > 2.0)
			{
				adultFactor = 1.3;
			}
			return 1.0 + (adultFactor - 1.0) * Math.Max(0.0, Math.Min(1.0, BearInheritance.Finite(maturity) ? maturity : 0.0));
		}

		internal static double Apply(double nativeBase, double factor)
		{
			return nativeBase * factor;
		}
	}
	internal static class BearGenetics
	{
		private sealed class Cache
		{
			internal string Raw = "";

			internal BearGenes? Value;
		}

		internal const string Key = "zf_bjorn_genes_v1";

		internal const string PendingKey = "zf_bjorn_child_v1";

		internal static ConfigEntry<float> MaleFactor = null;

		internal static ConfigEntry<bool> Trace = null;

		private static ConfigEntry<float>[] weights = null;

		private static ConfigEntry<float>[] foundations = null;

		private static bool validating;

		private static float next;

		private static double[] validWeights = (double[])BearInheritance.DefaultWeights.Clone();

		private static double[] validFoundation = (double[])BearInheritance.DefaultFoundation.Clone();

		private static readonly Dictionary<string, Cache> cache = new Dictionary<string, Cache>();

		private static ZNet? world;

		internal static double[] Weights => (double[])validWeights.Clone();

		internal static double[] Foundation => (double[])validFoundation.Clone();

		internal static bool IsBear(Component? c)
		{
			if (Object.op_Implicit((Object)(object)c))
			{
				return AnimalSexState.Species(c) == "Bjorn";
			}
			return false;
		}

		internal static void Configure(ConfigFile config)
		{
			//IL_001c: 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_0029: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			ConfigDescription description = new ConfigDescription("Server-synchronized Bjorn genetics; nonnegative finite weights, at least one positive. Invalid groups restore defaults. Variants have no statistics bonuses; Bjorn/Lox male health and female riding stamina each have a separate 10% sex bonus.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} });
			MaleFactor = config.Bind<float>("Server Rules", "Male linear size factor", 1.3f, new ConfigDescription("Linear dimensions of recorded males only. Hermaphrodite/unknown keep native size. Uses existing growth clock. Valid range 1..2; invalid restores 1.30.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
			weights = (from i in Enumerable.Range(0, 3)
				select config.Bind<float>("Server Rules", "Bjorn inheritance G" + (i + 1) + " weight", (float)BearInheritance.DefaultWeights[i], description)).ToArray();
			foundations = (from i in Enumerable.Range(0, 4)
				select config.Bind<float>("Server Rules", "Bjorn foundation " + BearInheritance.Variants[i] + " weight", 0.25f, description)).ToArray();
			Trace = config.Bind<bool>("Client", "Genetics and size diagnostics", false, "State-change diagnostics only. No per-frame tree calculation or log. zf_genetics_trace on/off.");
			Validate();
		}

		internal static void Validate()
		{
			if (validating || weights == null)
			{
				return;
			}
			validating = true;
			try
			{
				Group(weights, BearInheritance.DefaultWeights, ref validWeights, "G1/G2/G3 weights");
				Group(foundations, BearInheritance.DefaultFoundation, ref validFoundation, "foundation weights");
				if (!BearInheritance.Finite(MaleFactor.Value) || MaleFactor.Value < 1f || MaleFactor.Value > 2f)
				{
					Plugin.Error("SIZE invalid male factor; restored 1.30.");
					MaleFactor.Value = 1.3f;
				}
			}
			finally
			{
				validating = false;
			}
			static void Group(ConfigEntry<float>[] entries, double[] defaults, ref double[] valid, string label)
			{
				try
				{
					valid = BearInheritance.Normalize(((IEnumerable<ConfigEntry<float>>)entries).Select((Func<ConfigEntry<float>, double>)((ConfigEntry<float> e) => e.Value)).ToArray(), entries.Length);
				}
				catch (ArgumentException ex)
				{
					valid = (double[])defaults.Clone();
					Plugin.Error("GENETICS invalid " + label + ": " + ex.Message + "; restored defaults.");
					for (int num = 0; num < entries.Length; num++)
					{
						entries[num].Value = (float)defaults[num];
					}
				}
			}
		}

		internal static BearGenes? Read(Component? c)
		{
			ZNetView val = (Object.op_Implicit((Object)(object)c) ? c.GetComponent<ZNetView>() : null);
			if (!IsBear(c) || !Object.op_Implicit((Object)(object)val) || !val.IsValid())
			{
				return null;
			}
			return Read(val.GetZDO());
		}

		internal static BearGenes? Read(ZDO z)
		{
			return Decode(z.GetString("zf_bjorn_genes_v1", ""));
		}

		internal static BearGenes? Decode(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return null;
			}
			if (cache.TryGetValue(raw, out Cache value))
			{
				return value.Value;
			}
			BearGenes bearGenes = null;
			try
			{
				if (raw.Length > 12000)
				{
					throw new ArgumentException("Genetic record exceeds bound");
				}
				bearGenes = PresetJson.FromJson<BearGenes>(raw);
				if (!BearInheritance.Valid(bearGenes))
				{
					throw new ArgumentException("Invalid/unsupported bounded schema");
				}
			}
			catch (Exception ex)
			{
				bearGenes = null;
				Plugin.Error("GENETICS existing data preserved, operation refused: " + ex.Message);
			}
			if (cache.Count >= 512)
			{
				cache.Clear();
			}
			cache[raw] = new Cache
			{
				Raw = raw,
				Value = bearGenes
			};
			return bearGenes;
		}

		internal static BearGenes FoundationRecord(string origin)
		{
			string id = Guid.NewGuid().ToString("N");
			string seed = Guid.NewGuid().ToString("N");
			return BearInheritance.Complete(new BearGenes
			{
				id = id,
				origin = origin
			}, Foundation, Array.Empty<double>(), seed);
		}

		internal static BearGenes? Ensure(Component c)
		{
			if (!IsBear(c))
			{
				return null;
			}
			ZNetView component = c.GetComponent<ZNetView>();
			if (!Object.op_Implicit((Object)(object)component) || !component.IsValid())
			{
				return null;
			}
			ZDO zDO = component.GetZDO();
			BearGenes bearGenes = Read(zDO);
			if (bearGenes != null || !Plugin.ConfigReady || !component.IsOwner() || !string.IsNullOrEmpty(zDO.GetString("zf_bjorn_genes_v1", "")))
			{
				return bearGenes;
			}
			BearGenes bearGenes2 = FoundationRecord("foundation-or-migration");
			Write(zDO, "zf_bjorn_genes_v1", bearGenes2, "foundation/migration");
			return bearGenes2;
		}

		private static void Write(ZDO z, string key, BearGenes genes, string reason)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!BearInheritance.Valid(genes))
			{
				throw new InvalidOperationException("Refused invalid genetic record");
			}
			if (key == "zf_bjorn_child_v1")
			{
				genes.conceptionToken = z.GetLong(ZDOVars.s_pregnant, 0L);
			}
			z.Set(key, PresetJson.ToJson(genes));
			if (Trace.Value)
			{
				Plugin.Info(string.Format("GENETICS {0} ZDO={1} owner={2} id={3} sex={4} variant={5} ancestry={6}/{7}/{8} weights={9} probabilities={10} seed={11}", reason, z.m_uid, z.GetOwner(), genes.id, z.GetInt("zf_sex_v1", 0), genes.variant, genes.g1.Count((Ancestor a) => a.id.Length > 0), genes.g2.Count((Ancestor a) => a.id.Length > 0), genes.g3.Count((Ancestor a) => a.id.Length > 0), string.Join(",", genes.weights), string.Join(",", genes.birth), genes.seed));
			}
		}

		internal static void Conceived(Procreation mother)
		{
			if (IsBear((Component?)(object)mother) && CreatureState.Owner((Component)(object)mother, out ZDO zdo) && zdo.GetLong(ZDOVars.s_pregnant, 0L) != 0L && Decode(zdo.GetString("zf_bjorn_child_v1", ""))?.conceptionToken != zdo.GetLong(ZDOVars.s_pregnant, 0L))
			{
				Procreation approvedPartner = MatingAuthority.ApprovedPartner;
				BearGenes bearGenes = Ensure((Component)(object)mother);
				BearGenes bearGenes2 = (Object.op_Implicit((Object)(object)approvedPartner) ? Read((Component?)(object)approvedPartner) : null);
				if (bearGenes == null || bearGenes2 == null)
				{
					LegacyPending(mother, zdo);
					return;
				}
				BearGenes bearGenes3 = BearInheritance.Child(bearGenes, bearGenes2, Guid.NewGuid().ToString("N"));
				double[] array = Weights;
				double[] probabilities = BearInheritance.Probabilities(bearGenes3, array);
				BearInheritance.Complete(bearGenes3, probabilities, array, Guid.NewGuid().ToString("N"));
				Write(zdo, "zf_bjorn_child_v1", bearGenes3, "conception parents=" + bearGenes.id + "/" + bearGenes2.id);
			}
		}

		internal static BearGenes? Pending(Procreation mother)
		{
			if (!Plugin.ConfigReady || !IsBear((Component?)(object)mother) || !CreatureState.Owner((Component)(object)mother, out ZDO zdo))
			{
				return null;
			}
			string text = zdo.GetString("zf_bjorn_child_v1", "");
			BearGenes bearGenes = Decode(text);
			if (text.Length > 0 && bearGenes == null)
			{
				return null;
			}
			if (bearGenes != null && bearGenes.conceptionToken == zdo.GetLong(ZDOVars.s_pregnant, 0L))
			{
				return bearGenes;
			}
			if (text.Length > 0)
			{
				zdo.Set("zf_bjorn_child_v1", "");
			}
			if (zdo.GetLong(ZDOVars.s_pregnant, 0L) != 0L)
			{
				LegacyPending(mother, zdo);
				return Decode(zdo.GetString("zf_bjorn_child_v1", ""));
			}
			return null;
		}

		private static void LegacyPending(Procreation mother, ZDO z)
		{
			if (string.IsNullOrEmpty(z.GetString("zf_bjorn_child_v1", "")))
			{
				BearGenes genes = FoundationRecord("legacy-unrecorded-conception");
				Write(z, "zf_bjorn_child_v1", genes, "legacy pregnancy, deadline untouched, parents unknown");
			}
		}

		internal static void Born(GameObject baby, Procreation mother, BearGenes? child)
		{
			if (IsBear((Component?)(object)baby.transform) && child != null && CreatureState.Owner((Component)(object)baby.transform, out ZDO zdo))
			{
				Write(zdo, "zf_bjorn_genes_v1", child, "native birth");
				ApplyIndividual(baby, child);
				if (CreatureState.Owner((Component)(object)mother, out ZDO zdo2))
				{
					zdo2.Set("zf_bjorn_child_v1", "");
				}
			}
		}

		internal static void Grown(Component baby, GameObject adult)
		{
			if (IsBear(baby) && IsBear((Component?)(object)adult.transform) && CreatureState.Owner((Component)(object)adult.transform, out ZDO zdo))
			{
				BearGenes bearGenes = Ensure(baby);
				if (bearGenes != null)
				{
					Write(zdo, "zf_bjorn_genes_v1", bearGenes, "native growth same identity/variant/lineage");
					ApplyIndividual(adult, bearGenes);
				}
			}
		}

		private static void ApplyIndividual(GameObject go, BearGenes genes)
		{
			Character component = go.GetComponent<Character>();
			if (Object.op_Implicit((Object)(object)component))
			{
				AnimalSexState.Ensure((Component)(object)component);
				SexBody.Bind(component).Refresh();
				SexStats.Refresh(component);
				BearAppearance.Bind(component).Refresh(genes);
			}
		}

		internal static void Tick()
		{
			if ((Object)(object)world != (Object)(object)ZNet.instance)
			{
				world = ZNet.instance;
				cache.Clear();
			}
			if (!Plugin.ConfigReady || Time.realtimeSinceStartup < next)
			{
				return;
			}
			next = Time.realtimeSinceStartup + 1f;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if (IsBear((Component?)(object)allCharacter))
				{
					Ensure((Component)(object)allCharacter);
					Procreation component = ((Component)allCharacter).GetComponent<Procreation>();
					if (Object.op_Implicit((Object)(object)component))
					{
						Pending(component);
					}
				}
				if (SexBody.Supported((Component)(object)allCharacter))
				{
					SexBody.Bind(allCharacter).Refresh();
					SexStats.Refresh(allCharacter);
				}
				if (IsBear((Component?)(object)allCharacter))
				{
					BearAppearance.Bind(allCharacter).Refresh(Read((Component?)(object)allCharacter));
				}
			}
		}

		internal static bool CanConceive(Component mother, Component mate)
		{
			BearGenes bearGenes = Ensure(mother);
			BearGenes bearGenes2 = Read(mate);
			if (bearGenes == null || bearGenes2 == null)
			{
				return false;
			}
			try
			{
				BearInheritance.Probabilities(BearInheritance.Child(bearGenes, bearGenes2, "preview"), Weights);
				return true;
			}
			catch (ArgumentException)
			{
				return false;
			}
		}
	}
	[HarmonyPatch(typeof(Procreation), "Procreate")]
	internal static class BearBirth
	{
		private sealed class Scope
		{
			internal Procreation Mother;

			internal BearGenes? Child;
		}

		[ThreadStatic]
		private static Scope? scope;

		[HarmonyPrefix]
		private static bool Prefix(Procreation __instance, out Scope? __state)
		{
			__state = scope;
			scope = (BearGenetics.IsBear((Component?)(object)__instance) ? new Scope
			{
				Mother = __instance,
				Child = BearGenetics.Pending(__instance)
			} : null);
			if (scope != null && CreatureState.Owner((Component)(object)__instance, out ZDO zdo) && zdo.GetLong(ZDOVars.s_pregnant, 0L) != 0L)
			{
				return scope.Child != null;
			}
			return true;
		}

		[HarmonyFinalizer]
		private static Exception? Finalizer(Exception? __exception, Scope? __state)
		{
			scope = __state;
			return __exception;
		}

		private static GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(prefab, pos, rot);
			if (scope != null)
			{
				BearGenetics.Born(val, scope.Mother, scope.Child);
			}
			return val;
		}

		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source)
		{
			int replaced = 0;
			foreach (CodeInstruction item in source)
			{
				if (item.operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(Object) && methodInfo.Name == "Instantiate" && methodInfo.IsGenericMethod && methodInfo.GetGenericArguments()[0] == typeof(GameObject) && methodInfo.GetParameters().Length == 3)
				{
					item.operand = AccessTools.Method(typeof(BearBirth), "Spawn", (Type[])null, (Type[])null);
					replaced++;
				}
				yield return item;
			}
			if (replaced != 1)
			{
				throw new InvalidOperationException("Native birth contract changed: expected one native Instantiate, got " + replaced);
			}
		}
	}
	internal sealed class BearMount : MonoBehaviour
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<Character, bool> <>9__10_0;

			public static Func<Character, float> <>9__10_1;

			public static Func<Character, BearMount> <>9__10_2;

			public static Func<BearMount, bool> <>9__10_3;

			public static ConsoleEvent <>9__11_0;

			internal bool <Select>b__10_0(Character c)
			{
				//IL_002d: 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)
				if (Object.op_Implicit((Object)(object)c) && c.IsTamed() && Utils.GetPrefabName(((Component)c).gameObject) == "Bjorn")
				{
					return Vector3.Distance(((Component)c).transform.position, ((Component)Player.m_localPlayer).transform.position) < 15f;
				}
				return false;
			}

			internal float <Select>b__10_1(Character c)
			{
				//IL_0006: 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)
				return Vector3.Distance(((Component)c).transform.position, ((Component)Player.m_localPlayer).transform.position);
			}

			internal BearMount <Select>b__10_2(Character c)
			{
				return ((Component)c).GetComponent<BearMount>();
			}

			internal bool <Select>b__10_3(BearMount c)
			{
				if (Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)c.mount) && Object.op_Implicit((Object)(object)c.bone))
				{
					return Object.op_Implicit((Object)(object)c.mount.getSaddle());
				}
				return false;
			}

			internal void <RegisterCommands>b__11_0(ConsoleEventArgs args)
			{
				if (args.Args.Length == 1 || args.Args[1] == "show")
				{
					Show(args.Context);
				}
				else
				{
					args.Context.AddString(Texts.T("Les anciennes commandes de modification sont remplacées par F9 et les presets.", "Legacy editing commands are replaced by F9 presets."));
				}
			}
		}

		private Mountable mount;

		private Transform visual;

		private Transform bone;

		private static BearMount? preview;

		internal static void Bind(Mountable value)
		{
			if (!(Utils.GetPrefabName(((Component)value).gameObject) != "Bjorn") && !Object.op_Implicit((Object)(object)((Component)value).GetComponent<Growup>()))
			{
				BearMount bearMount = ((Component)value).GetComponent<BearMount>();
				if (!Object.op_Implicit((Object)(object)bearMount))
				{
					bearMount = ((Component)value).gameObject.AddComponent<BearMount>();
				}
				bearMount.mount = value;
				bearMount.visual = ((Component)value).transform.Find("Visual");
				bearMount.bone = (Object.op_Implicit((Object)(object)bearMount.visual) ? bearMount.visual.Find("Armature/Root/CoG/Hip/Spine_01/Spine_02") : null);
				MountRiding.Bind(((Component)value).GetComponent<Character>());
				bearMount.Apply();
			}
		}

		private void LateUpdate()
		{
			Apply();
		}

		internal void Apply()
		{
			MountPlacement mountPlacement = MountPlacement.Bind(((Component)this).GetComponent<Character>());
			if (Object.op_Implicit((Object)(object)mountPlacement) && mountPlacement.Ready())
			{
				mountPlacement.Apply();
			}
		}

		private static bool Valid(Vector3 v)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			if (SaddleGeometry.Finite(v) && Math.Abs(v.x) <= 1000f && Math.Abs(v.y) <= 1000f)
			{
				return Math.Abs(v.z) <= 1000f;
			}
			return false;
		}

		private void Begin()
		{
			MountPlacement mountPlacement = MountPlacement.Bind(((Component)this).GetComponent<Character>());
			if (!Object.op_Implicit((Object)(object)mountPlacement) || !mountPlacement.Ready())
			{
				throw new InvalidOperationException("Saddle reference not loaded");
			}
			mountPlacement.Capture().SaveConfig("Bjorn");
			preview = this;
			Apply();
		}

		private void Fit(Terminal context)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			MountPlacement mountPlacement = MountPlacement.Bind(((Component)this).GetComponent<Character>());
			if (!Object.op_Implicit((Object)(object)mountPlacement) || !mountPlacement.Ready())
			{
				throw new InvalidOperationException("Saddle reference not loaded");
			}
			if (mountPlacement.TryFit(PlacementPreset.Config("Bjorn", mountPlacement.ReferenceScale), out PlacementPreset candidate, out string explanation))
			{
				candidate.SaveConfig("Bjorn");
				Apply();
			}
			context.AddString(explanation);
		}

		private static BearMount? Select()
		{
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return null;
			}
			IDoodadController doodadController = Player.m_localPlayer.GetDoodadController();
			Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
			if (val != null)
			{
				Character character = val.GetCharacter();
				if (Object.op_Implicit((Object)(object)character))
				{
					return ((Component)character).GetComponent<BearMount>();
				}
			}
			return (from c in Character.GetAllCharacters()
				where Object.op_Implicit((Object)(object)c) && c.IsTamed() && Utils.GetPrefabName(((Component)c).gameObject) == "Bjorn" && Vector3.Distance(((Component)c).transform.position, ((Component)Player.m_localPlayer).transform.position) < 15f
				orderby Vector3.Distance(((Component)c).transform.position, ((Component)Player.m_localPlayer).transform.position)
				select ((Component)c).GetComponent<BearMount>()).FirstOrDefault((BearMount c) => Object.op_Implicit((Object)(object)c) && Object.op_Implicit((Object)(object)c.mount) && Object.op_Implicit((Object)(object)c.bone) && Object.op_Implicit((Object)(object)c.mount.getSaddle()));
		}

		internal static void RegisterCommands()
		{
			//IL_003d: 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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			string text = Texts.T("Diagnostic Bjorn : show. Réglages dans F9 / presets.", "Bjorn diagnostic: show. Edit through F9 / presets.");
			object obj = <>c.<>9__11_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					if (args.Args.Length == 1 || args.Args[1] == "show")
					{
						Show(args.Context);
					}
					else
					{
						args.Context.AddString(Texts.T("Les anciennes commandes de modification sont remplacées par F9 et les presets.", "Legacy editing commands are replaced by F9 presets."));
					}
				};
				<>c.<>9__11_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("zf_mount", text, (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}

		private static float Parse(string value)
		{
			return float.Parse(value.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture);
		}

		private static Vector3 Wrapped(Vector3 value)
		{
			//IL_0005: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(Mathf.DeltaAngle(0f, value.x), Mathf.DeltaAngle(0f, value.y), Mathf.DeltaAngle(0f, value.z));
		}

		private static void Show(Terminal context)
		{
			//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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			object[] obj = new object[6]
			{
				Plugin.PlacementEnabled.Value,
				null,
				null,
				null,
				null,
				null
			};
			Vector3 value = Plugin.ModelPosition.Value;
			obj[1] = ((Vector3)(ref value)).ToString("F4");
			value = Plugin.ModelRotation.Value;
			obj[2] = ((Vector3)(ref value)).ToString("F3");
			value = Plugin.ModelScale.Value;
			obj[3] = ((Vector3)(ref value)).ToString("F4");
			value = Plugin.SeatPosition.Value;
			obj[4] = ((Vector3)(ref value)).ToString("F4");
			value = Plugin.SeatRotation.Value;
			obj[5] = ((Vector3)(ref value)).ToString("F3");
			string text = string.Format("BJORN PLACEMENT enabled={0} model={1} rot={2} scale={3} seat={4} seatRot={5}; origin=Spine_02, axes=Visual; calibration status requires human visual check.", obj);
			context.AddString(text + "\n" + Texts.T("Origine : Spine_02, axes du modèle Visual. Contrôle visuel humain nécessaire.", "Origin: Spine_02, Visual axes. Human visual check required."));
			Plugin.Info(text);
		}
	}
	[HarmonyPatch(typeof(Mountable), "Awake")]
	internal static class BindBearMount
	{
		[HarmonyPostfix]
		private static void Postfix(Mountable __instance)
		{
			BearMount.Bind(__instance);
		}
	}
	[HarmonyPatch(typeof(Mountable), "ResetMountPoint")]
	internal static class PreserveIndependentSeat
	{
		[HarmonyPostfix]
		private static void Postfix(Mountable __instance)
		{
			((Component)__instance).GetComponent<BearMount>()?.Apply();
		}
	}
	internal static class BreedingDiagnostics
	{
		private sealed class Request
		{
			internal long Client;

			internal float Expires;

			internal Vector3 Position;

			internal bool French;

			internal bool Defense;
		}

		private sealed class Attempts
		{
			internal int Count;

			internal float Last;

			internal float Interval;

			internal float NextLog;

			internal string State = "";
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<KeyValuePair<string, Request>, bool> <>9__12_0;

			public static Func<KeyValuePair<string, Request>, string> <>9__12_1;

			public static ConsoleEvent <>9__13_0;

			public static ConsoleEvent <>9__13_1;

			internal bool <Tick>b__12_0(KeyValuePair<string, Request> p)
			{
				return Time.realtimeSinceStartup > p.Value.Expires;
			}

			internal string <Tick>b__12_1(KeyValuePair<string, Request> p)
			{
				return p.Key;
			}

			internal void <Register>b__13_0(ConsoleEventArgs args)
			{
				QuerySnapshot(new <>c__DisplayClass13_0
				{
					args = args
				}.<Register>b__2, defense: true);
			}

			internal void <Register>b__13_1(ConsoleEventArgs args)
			{
				QuerySnapshot(new <>c__DisplayClass13_1
				{
					args = args
				}.<Register>b__3, defense: false);
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass13_0
		{
			public ConsoleEventArgs args;

			internal void <Register>b__2(string s)
			{
				args.Context.AddString(s);
			}
		}

		[CompilerGenerated]
		private sealed class <>c__DisplayClass13_1
		{
			public ConsoleEventArgs args;

			internal void <Register>b__3(string s)
			{
				args.Context.AddString(s);
			}
		}

		private const string Query = "ZF_BreedingQuery_v2";

		private const string OwnerQuery = "ZF_BreedingOwnerQuery_v2";

		private const string Reply = "ZF_BreedingReply_v2";

		private const string Result = "ZF_BreedingResult_v2";

		private static readonly Dictionary<string, Request> requests = new Dictionary<string, Request>();

		private static readonly Dictionary<ZDOID, Attempts> attempts = new Dictionary<ZDOID, Attempts>();

		private static ZRoutedRpc? rpc;

		private static ZNet? world;

		private static Action<string>? output;

		private static string localRequest = "";

		internal static void Tick()
		{
			if (!Object.op_Implicit((Object)(object)ZNet.instance) || !Plugin.ConfigReady || ZRoutedRpc.instance == null)
			{
				rpc = null;
				world = null;
				requests.Clear();
				attempts.Clear();
				output = null;
				return;
			}
			if ((Object)(object)world != (Object)(object)ZNet.instance)
			{
				world = ZNet.instance;
				requests.Clear();
				attempts.Clear();
			}
			if (rpc != ZRoutedRpc.instance)
			{
				rpc = ZRoutedRpc.instance;
				rpc.Register<ZPackage>("ZF_BreedingQuery_v2", (Action<long, ZPackage>)ReceiveQuery);
				rpc.Register<ZPackage>("ZF_BreedingOwnerQuery_v2", (Action<long, ZPackage>)ReceiveOwnerQuery);
				rpc.Register<ZPackage>("ZF_BreedingReply_v2", (Action<long, ZPackage>)ReceiveReply);
				rpc.Register<ZPackage>("ZF_BreedingResult_v2", (Action<long, ZPackage>)ReceiveResult);
			}
			string[] array = (from p in requests
				where Time.realtimeSinceStartup > p.Value.Expires
				select p.Key).ToArray();
			foreach (string key in array)
			{
				requests.Remove(key);
			}
		}

		internal static void Register()
		{
			//IL_0042: 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_0038: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to inva