Decompiled source of Bear Taming v1.0.0

plugins/nick008-Bear_Taming.dll

Decompiled 15 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Nick008TameableBear;

[BepInProcess("valheim.exe")]
[BepInPlugin("nick008.tameable_and_breadable_and_ridable_bear", "nick008-tameable_and_breadable_and_ridable_bear", "1.2.1")]
public sealed class Nick008TameableBearPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	private static class ZNetSceneAwakePatch
	{
		[HarmonyPrefix]
		private static void Prefix(ZNetScene __instance)
		{
			try
			{
				GameObject cub = RegisterCubBeforeSceneAwake(__instance);
				ConfigureBearCoreBeforeSceneAwake(__instance, cub);
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogError((object)("[nick008-bear] Early bear setup failed: " + ex));
				}
			}
		}
	}

	[HarmonyPatch(typeof(Tameable), "RPC_SetSaddle")]
	private static class BearSaddleRpcPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Tameable __instance, object[] __args)
		{
			try
			{
				if (!IsBearTameable(__instance))
				{
					return;
				}
				bool flag = false;
				if (__args != null)
				{
					for (int num = __args.Length - 1; num >= 0; num--)
					{
						if (__args[num] is bool)
						{
							flag = (bool)__args[num];
							break;
						}
					}
				}
				Log.LogWarning((object)("[nick008-bear][DIAG] Bjorn RPC_SetSaddle fired, haveSaddle=" + flag));
				SetBearSaddleVisual(__instance, flag);
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogWarning((object)("[nick008-bear] RPC saddle visual sync failed: " + ex.Message));
				}
			}
		}
	}

	[HarmonyPatch]
	private static class BearSadleAwakePatch
	{
		private static MethodBase TargetMethod()
		{
			Type type = AccessTools.TypeByName("Sadle");
			if (!(type != null))
			{
				return null;
			}
			return AccessTools.Method(type, "Awake", (Type[])null, (Type[])null);
		}

		private static void Prefix(object __instance)
		{
			try
			{
				Component val = (Component)((__instance is Component) ? __instance : null);
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.gameObject == (Object)null) && ((Object)val.gameObject).name.StartsWith("nick008_BearSaddle", StringComparison.Ordinal))
				{
					PrepareBearSaddleRuntimeRefs(val, null);
				}
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogWarning((object)("[nick008-bear] Sadle.Awake preparation failed: " + ex.Message));
				}
			}
		}
	}

	[HarmonyPatch(typeof(Sadle), "ApplyControlls")]
	private static class BearSadleControlsPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Sadle __instance, Vector3 moveDir, Vector3 lookDir, bool run, bool autoRun, bool block)
		{
			//IL_004e: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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_00ba: 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)
			try
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				Character character = __instance.GetCharacter();
				if ((Object)(object)character == (Object)null || (Object)(object)((Component)character).gameObject == (Object)null || character.GetLevel() < 3)
				{
					return;
				}
				Tameable component = ((Component)character).GetComponent<Tameable>();
				if (!IsBearTameable(component))
				{
					return;
				}
				Vector3 val = lookDir;
				val.y = 0f;
				if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
				{
					((Vector3)(ref val)).Normalize();
				}
				else
				{
					val = ((Component)character).transform.forward;
					val.y = 0f;
					if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
					{
						((Vector3)(ref val)).Normalize();
					}
				}
				float z = moveDir.z;
				if (Mathf.Abs(z) < 0.05f)
				{
					mountedBearDesiredDirection = Vector3.zero;
				}
				else
				{
					mountedBearDesiredDirection = val * Mathf.Sign(z);
				}
				mountedBearControlId = ((Object)character).GetInstanceID();
				mountedBearWantsRun = run || autoRun;
				mountedBearControlTime = Time.time;
				character.SetMoveDir(mountedBearDesiredDirection);
				character.SetRun(mountedBearWantsRun);
				character.SetWalk(false);
				character.m_walkSpeed = Mathf.Max(character.m_walkSpeed, 1.5f);
				character.m_speed = Mathf.Max(character.m_speed, 3f);
				character.m_runSpeed = Mathf.Max(character.m_runSpeed, 7f);
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogWarning((object)("[nick008-bear] 1.1.3 level3 control safeguard failed: " + ex.Message));
				}
			}
		}
	}

	[HarmonyPatch(typeof(Player), "SetControls")]
	private static class BearMountedSuppressPlayerAttackPatch
	{
		[HarmonyPrefix]
		private static void Prefix(Player __instance, ref bool attack, ref bool secondaryAttack)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (Object)(object)GetControlledBearSaddle(__instance) != (Object)null)
			{
				attack = false;
				secondaryAttack = false;
			}
		}
	}

	[HarmonyPatch(typeof(Player), "Update")]
	private static class BearMountedAttackPatch
	{
		private static void TriggerBearAttack(Humanoid bear, int preferredIndex)
		{
			if ((Object)(object)bear == (Object)null || ((Character)bear).InAttack() || bear.m_defaultItems == null || bear.m_defaultItems.Length == 0)
			{
				return;
			}
			int num = preferredIndex;
			if (num < 0 || num >= bear.m_defaultItems.Length || (Object)(object)bear.m_defaultItems[num] == (Object)null)
			{
				num = 0;
			}
			if (num >= bear.m_defaultItems.Length || (Object)(object)bear.m_defaultItems[num] == (Object)null)
			{
				return;
			}
			ItemDrop component = bear.m_defaultItems[num].GetComponent<ItemDrop>();
			if (!((Object)(object)component == (Object)null))
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(Humanoid), "m_rightItem");
				if (!(fieldInfo == null))
				{
					fieldInfo.SetValue(bear, component.m_itemData);
					((Character)bear).StartAttack((Character)null, false);
				}
			}
		}

		[HarmonyPostfix]
		private static void Postfix(Player __instance)
		{
			try
			{
				if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				Sadle controlledBearSaddle = GetControlledBearSaddle(__instance);
				if ((Object)(object)controlledBearSaddle == (Object)null)
				{
					return;
				}
				Character character = controlledBearSaddle.GetCharacter();
				Humanoid val = (Humanoid)(object)((character is Humanoid) ? character : null);
				if (!((Object)(object)val == (Object)null))
				{
					if (ZInput.GetButtonDown("Attack"))
					{
						TriggerBearAttack(val, 0);
					}
					else if (ZInput.GetButtonDown("SecondaryAttack"))
					{
						TriggerBearAttack(val, 1);
					}
				}
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogWarning((object)("[nick008-bear] 1.1.3 mounted attack failed: " + ex.Message));
				}
			}
		}
	}

	[HarmonyPatch(typeof(Tameable), "GetHoverText")]
	private static class BearRideHoverPatch
	{
		[HarmonyPostfix]
		private static void Postfix(Tameable __instance, ref string __result)
		{
			try
			{
				if (IsBearTameable(__instance) && BearHasSaddle(__instance) && !string.IsNullOrEmpty(__result) && __result.IndexOf("Nasednout", StringComparison.OrdinalIgnoreCase) < 0)
				{
					__result = "<color=yellow>[LeftAlt + E]</color> Nasednout\\n" + __result;
				}
			}
			catch
			{
			}
		}
	}

	[HarmonyPatch]
	private static class BearDirectRidePatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			MethodInfo[] methods = typeof(Tameable).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo method in methods)
			{
				if (method.Name != "Interact" || method.ReturnType != typeof(bool))
				{
					continue;
				}
				ParameterInfo[] parameters = method.GetParameters();
				bool hasHumanoid = false;
				for (int j = 0; j < parameters.Length; j++)
				{
					if (typeof(Humanoid).IsAssignableFrom(parameters[j].ParameterType))
					{
						hasHumanoid = true;
						break;
					}
				}
				if (hasHumanoid)
				{
					yield return method;
				}
			}
		}

		private static bool TryRide(Component saddle, Humanoid humanoid, out bool ridden)
		{
			ridden = false;
			if ((Object)(object)saddle == (Object)null || (Object)(object)humanoid == (Object)null)
			{
				return false;
			}
			PrepareBearSaddleRuntimeRefs(saddle, ((Object)(object)saddle.GetComponentInParent<Tameable>() != (Object)null) ? ((Component)saddle.GetComponentInParent<Tameable>()).gameObject : null);
			MethodInfo[] methods = ((object)saddle).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name != "Interact" || methodInfo.ReturnType != typeof(bool))
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				object[] array = new object[parameters.Length];
				bool flag = true;
				bool flag2 = false;
				for (int j = 0; j < parameters.Length; j++)
				{
					Type parameterType = parameters[j].ParameterType;
					if (typeof(Humanoid).IsAssignableFrom(parameterType))
					{
						array[j] = humanoid;
						flag2 = true;
						continue;
					}
					if (parameterType == typeof(bool))
					{
						array[j] = false;
						continue;
					}
					flag = false;
					break;
				}
				if (flag && flag2)
				{
					object obj = methodInfo.Invoke(saddle, array);
					if (obj is bool)
					{
						ridden = (bool)obj;
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryForceRide(Component saddle, Humanoid humanoid, out bool attached, out bool controllerStarted, out bool validUser)
		{
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//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)
			attached = false;
			controllerStarted = false;
			validUser = false;
			Player val = (Player)(object)((humanoid is Player) ? humanoid : null);
			if ((Object)(object)saddle == (Object)null || (Object)(object)val == (Object)null)
			{
				return false;
			}
			Tameable componentInParent = saddle.GetComponentInParent<Tameable>();
			GameObject val2 = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).gameObject : null);
			PrepareBearSaddleRuntimeRefs(saddle, val2);
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = ((object)saddle).GetType().GetField("m_attachPoint", bindingAttr);
			FieldInfo field2 = ((object)saddle).GetType().GetField("m_attachAnimation", bindingAttr);
			FieldInfo field3 = ((object)saddle).GetType().GetField("m_detachOffset", bindingAttr);
			FieldInfo field4 = ((object)saddle).GetType().GetField("m_haveValidUser", bindingAttr);
			Transform val3 = (Transform)((field != null) ? /*isinst with value type is only supported in some contexts*/: null);
			string text = ((field2 != null) ? (field2.GetValue(saddle) as string) : null);
			Vector3 val4 = Vector3.zero;
			if (field3 != null)
			{
				object value = field3.GetValue(saddle);
				if (value is Vector3)
				{
					val4 = (Vector3)value;
				}
			}
			if ((Object)(object)val3 == (Object)null)
			{
				return false;
			}
			if (string.IsNullOrEmpty(text))
			{
				text = "attach_lox";
			}
			try
			{
				IDoodadController val5 = (IDoodadController)(object)((saddle is IDoodadController) ? saddle : null);
				if (val5 != null)
				{
					MethodInfo method = typeof(Player).GetMethod("StartDoodadControl", bindingAttr, null, new Type[1] { typeof(IDoodadController) }, null);
					if (method != null)
					{
						method.Invoke(val, new object[1] { val5 });
						controllerStarted = true;
					}
				}
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogWarning((object)("[nick008-bear] Force mount StartDoodadControl failed: " + ex.Message));
				}
			}
			try
			{
				MethodInfo method2 = typeof(Character).GetMethod("AttachStart", bindingAttr, null, new Type[8]
				{
					typeof(Transform),
					typeof(GameObject),
					typeof(bool),
					typeof(bool),
					typeof(bool),
					typeof(string),
					typeof(Vector3),
					typeof(Transform)
				}, null);
				if (method2 != null)
				{
					method2.Invoke(val, new object[8] { val3, val2, false, false, false, text, val4, null });
				}
			}
			catch (Exception ex2)
			{
				if (Log != null)
				{
					Log.LogWarning((object)("[nick008-bear] Force mount AttachStart failed: " + ex2.Message));
				}
			}
			try
			{
				MethodInfo method3 = typeof(Character).GetMethod("IsAttached", bindingAttr, null, Type.EmptyTypes, null);
				if (method3 != null)
				{
					object obj = method3.Invoke(val, null);
					if (obj is bool)
					{
						attached = (bool)obj;
					}
				}
			}
			catch
			{
			}
			try
			{
				if (field4 != null)
				{
					object value2 = field4.GetValue(saddle);
					if (value2 is bool)
					{
						validUser = (bool)value2;
					}
					if (controllerStarted && !validUser)
					{
						field4.SetValue(saddle, true);
						validUser = true;
					}
				}
			}
			catch
			{
			}
			if (!attached)
			{
				return controllerStarted;
			}
			return true;
		}

		private static bool Prefix(Tameable __instance, object[] __args, ref bool __result)
		{
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			try
			{
				if (!IsBearTameable(__instance) || !BearHasSaddle(__instance))
				{
					return true;
				}
				if (!Input.GetKey((KeyCode)308) && !Input.GetKey((KeyCode)307))
				{
					return true;
				}
				Humanoid val = null;
				bool flag = false;
				if (__args != null)
				{
					bool flag2 = false;
					for (int i = 0; i < __args.Length; i++)
					{
						if (__args[i] is Humanoid)
						{
							val = (Humanoid)__args[i];
						}
						else if (__args[i] is bool && !flag2)
						{
							flag = (bool)__args[i];
							flag2 = true;
						}
					}
				}
				if ((Object)(object)val == (Object)null || flag)
				{
					return true;
				}
				Component bearSaddleComponent = GetBearSaddleComponent(__instance);
				if ((Object)(object)bearSaddleComponent == (Object)null)
				{
					if (Log != null)
					{
						Log.LogWarning((object)"[nick008-bear] LeftAlt+E mount attempt: bear saddle component is null.");
					}
					return true;
				}
				bool ridden;
				bool flag3 = TryRide(bearSaddleComponent, val, out ridden);
				if (Log != null)
				{
					Log.LogInfo((object)("[nick008-bear] LeftAlt+E mount attempt. Saddle.Interact called=" + flag3 + ", result=" + ridden));
					if (!ridden)
					{
						try
						{
							BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
							FieldInfo field = ((object)bearSaddleComponent).GetType().GetField("m_character", bindingAttr);
							FieldInfo field2 = ((object)bearSaddleComponent).GetType().GetField("m_nview", bindingAttr);
							FieldInfo field3 = ((object)bearSaddleComponent).GetType().GetField("m_tambable", bindingAttr);
							FieldInfo field4 = ((object)bearSaddleComponent).GetType().GetField("m_monsterAI", bindingAttr);
							FieldInfo field5 = ((object)bearSaddleComponent).GetType().GetField("m_attachPoint", bindingAttr);
							Character val2 = (Character)((field != null) ? /*isinst with value type is only supported in some contexts*/: null);
							ZNetView val3 = (ZNetView)((field2 != null) ? /*isinst with value type is only supported in some contexts*/: null);
							Tameable val4 = (Tameable)((field3 != null) ? /*isinst with value type is only supported in some contexts*/: null);
							MonsterAI val5 = (MonsterAI)((field4 != null) ? /*isinst with value type is only supported in some contexts*/: null);
							Transform val6 = (Transform)((field5 != null) ? /*isinst with value type is only supported in some contexts*/: null);
							object obj = null;
							bool flag4 = false;
							bool flag5 = false;
							bool flag6 = false;
							bool flag7 = false;
							try
							{
								MethodInfo method = ((object)bearSaddleComponent).GetType().GetMethod("GetUser", bindingAttr, null, Type.EmptyTypes, null);
								if (method != null)
								{
									obj = method.Invoke(bearSaddleComponent, null);
								}
							}
							catch
							{
							}
							try
							{
								FieldInfo field6 = ((object)bearSaddleComponent).GetType().GetField("m_haveValidUser", bindingAttr);
								if (field6 != null)
								{
									object value = field6.GetValue(bearSaddleComponent);
									if (value is bool)
									{
										flag4 = (bool)value;
									}
								}
							}
							catch
							{
							}
							try
							{
								MethodInfo methodInfo = (((Object)(object)val4 != (Object)null) ? ((object)val4).GetType().GetMethod("HaveRider", bindingAttr, null, Type.EmptyTypes, null) : null);
								if (methodInfo != null)
								{
									object obj4 = methodInfo.Invoke(val4, null);
									if (obj4 is bool)
									{
										flag5 = (bool)obj4;
									}
								}
							}
							catch
							{
							}
							try
							{
								flag6 = (Object)(object)val3 != (Object)null && val3.IsOwner();
							}
							catch
							{
							}
							try
							{
								flag7 = (Object)(object)val2 != (Object)null && val2.IsTamed();
							}
							catch
							{
							}
							float num = (((Object)(object)val != (Object)null) ? Vector3.Distance(((Component)val).transform.position, bearSaddleComponent.transform.position) : (-1f));
							Log.LogInfo((object)("[nick008-bear] Mount fail state: character=" + ((Object)(object)val2 != (Object)null) + ", tamed=" + flag7 + ", nview=" + ((Object)(object)val3 != (Object)null) + ", nviewValid=" + ((Object)(object)val3 != (Object)null && val3.IsValid()) + ", nviewOwner=" + flag6 + ", tameable=" + ((Object)(object)val4 != (Object)null) + ", haveRider=" + flag5 + ", monsterAI=" + ((Object)(object)val5 != (Object)null) + ", attachPoint=" + ((Object)(object)val6 != (Object)null) + ", haveValidUser=" + flag4 + ", getUser=" + ((obj != null) ? obj.ToString() : "<null>") + ", saddleActiveSelf=" + bearSaddleComponent.gameObject.activeSelf + ", saddleActiveHierarchy=" + bearSaddleComponent.gameObject.activeInHierarchy + ", userDistance=" + num.ToString("0.00") + ", colliders=" + bearSaddleComponent.GetComponents<Collider>().Length));
						}
						catch (Exception ex)
						{
							Log.LogWarning((object)("[nick008-bear] Mount fail diagnostic failed: " + ex.Message));
						}
					}
				}
				if (flag3 && ridden)
				{
					__result = true;
					return false;
				}
				if (Log != null)
				{
					Log.LogWarning((object)"[nick008-bear] Native Sadle.Interact still returned false. Check userDistance in Mount fail state.");
				}
				__result = false;
				return false;
			}
			catch (Exception ex2)
			{
				if (Log != null)
				{
					Log.LogWarning((object)("[nick008-bear] LeftAlt+E ride patch failed: " + ex2));
				}
				__result = false;
				return false;
			}
		}
	}

	public const string PluginGuid = "nick008.tameable_and_breadable_and_ridable_bear";

	public const string PluginName = "nick008-tameable_and_breadable_and_ridable_bear";

	public const string PluginVersion = "1.2.1";

	private const float TamingTime = 1500f;

	private const float FedDuration = 300f;

	private const float GrowTime = 2000f;

	private const int MaxNearbyBears = 5;

	private const float PregnancyChance = 0.66f;

	private const float PregnancyDuration = 90f;

	private const float CubScale = 0.55f;

	private const string BearPrefabName = "Bjorn";

	private const string LoxPrefabName = "Lox";

	private const string CubPrefabName = "nick008_BearCub";

	private const string SaddleObjectName = "nick008_BearSaddle";

	private const string SaddleVisualName = "nick008_BearSaddleVisual";

	private const string MountPointName = "nick008_BearMountPoint";

	private const string BearSaddleItemPrefabName = "nick008_BearSaddleItem";

	private const string BearSaddleItemDisplayName = "Bear Saddle";

	private const string BearSaddleItemDescription = "A sturdy saddle made for riding a tamed bear.";

	private const string BearSaddleRecipeName = "Recipe_nick008_BearSaddle";

	private const float Level3MountedScaleCap = 1.25f;

	internal static ManualLogSource Log;

	internal static Nick008TameableBearPlugin Instance;

	private static readonly string[] FoodPrefabNames = new string[4] { "Blueberries", "Honey", "RawMeat", "DeerMeat" };

	private int configuredSceneId = int.MinValue;

	private GameObject offspringRoot;

	private static bool ridingDiagnosticsDumped = false;

	private static readonly Dictionary<int, GameObject> saddleVisualCache = new Dictionary<int, GameObject>();

	private GameObject customSaddlePrefabRoot;

	private static int customSaddleConfiguredDbId = int.MinValue;

	private static int mountedBearControlId = -1;

	private static Vector3 mountedBearDesiredDirection = Vector3.zero;

	private static bool mountedBearWantsRun = false;

	private static float mountedBearControlTime = -999f;

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

	private static Character level3ScaledBear = null;

	private static Vector3 level3OriginalLocalScale = Vector3.one;

	private void Awake()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		new Harmony("nick008.tameable_and_breadable_and_ridable_bear").PatchAll();
		Log.LogInfo((object)"[nick008-bear] 1.2.1 LIVE loaded. Fixed leftover test taming/growth values to normal gameplay values; Bear Saddle and riding features unchanged.");
		((MonoBehaviour)this).StartCoroutine(WatchForCreatureDatabase());
	}

	internal static GameObject RegisterCubBeforeSceneAwake(ZNetScene scene)
	{
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Expected O, but got Unknown
		if ((Object)(object)scene == (Object)null || (Object)(object)Instance == (Object)null)
		{
			return null;
		}
		GameObject val = FindPrefabInSceneList(scene, "nick008_BearCub");
		if ((Object)(object)val != (Object)null)
		{
			return val;
		}
		GameObject val2 = FindPrefabInSceneList(scene, "Bjorn");
		if ((Object)(object)val2 == (Object)null)
		{
			if (Log != null)
			{
				Log.LogError((object)"[nick008-bear] Vanilla prefab 'Bjorn' was not found.");
			}
			return null;
		}
		if ((Object)(object)Instance.offspringRoot == (Object)null)
		{
			Instance.offspringRoot = new GameObject("nick008tameablebear_offspring_root");
			Instance.offspringRoot.transform.SetParent(((Component)Instance).transform, false);
			Instance.offspringRoot.SetActive(false);
		}
		GameObject val3 = Object.Instantiate<GameObject>(val2, Instance.offspringRoot.transform);
		((Object)val3).name = "nick008_BearCub";
		val3.transform.localScale = val3.transform.localScale * 0.55f;
		CharacterDrop component = val3.GetComponent<CharacterDrop>();
		if ((Object)(object)component != (Object)null)
		{
			Object.DestroyImmediate((Object)(object)component);
		}
		Tameable component2 = val3.GetComponent<Tameable>();
		if ((Object)(object)component2 != (Object)null)
		{
			Object.DestroyImmediate((Object)(object)component2);
		}
		Procreation component3 = val3.GetComponent<Procreation>();
		if ((Object)(object)component3 != (Object)null)
		{
			Object.DestroyImmediate((Object)(object)component3);
		}
		Growup val4 = val3.GetComponent<Growup>();
		if ((Object)(object)val4 == (Object)null)
		{
			val4 = val3.AddComponent<Growup>();
		}
		val4.m_grownPrefab = val2;
		val4.m_growTime = 2000f;
		scene.m_prefabs.Add(val3);
		if (Log != null)
		{
			Log.LogInfo((object)"[nick008-bear] Early-registered persistent bear cub prefab.");
		}
		return val3;
	}

	internal static bool ConfigureBearCoreBeforeSceneAwake(ZNetScene scene, GameObject cub)
	{
		if ((Object)(object)scene == (Object)null || (Object)(object)cub == (Object)null)
		{
			return false;
		}
		GameObject val = FindPrefabInSceneList(scene, "Bjorn");
		GameObject val2 = FindPrefabInSceneList(scene, "Lox");
		if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
		{
			if (Log != null)
			{
				Log.LogError((object)"[nick008-bear] Bjorn or Lox prefab was not found.");
			}
			return false;
		}
		MonsterAI component = val.GetComponent<MonsterAI>();
		Tameable component2 = val2.GetComponent<Tameable>();
		Procreation component3 = val2.GetComponent<Procreation>();
		if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null)
		{
			if (Log != null)
			{
				Log.LogError((object)"[nick008-bear] Required vanilla Bjorn/Lox components were not found.");
			}
			return false;
		}
		Tameable val3 = val.GetComponent<Tameable>();
		if ((Object)(object)val3 == (Object)null)
		{
			val3 = val.AddComponent<Tameable>();
			CopyPublicFields((Component)(object)val3, (Component)(object)component2);
		}
		val3.m_commandable = true;
		val3.m_startsTamed = false;
		val3.m_tamingTime = 1500f;
		val3.m_fedDuration = 300f;
		if (component.m_consumeItems == null)
		{
			component.m_consumeItems = new List<ItemDrop>();
		}
		Procreation val4 = val.GetComponent<Procreation>();
		if ((Object)(object)val4 == (Object)null)
		{
			val4 = val.AddComponent<Procreation>();
			CopyPublicFields((Component)(object)val4, (Component)(object)component3);
		}
		val4.m_maxCreatures = 5;
		val4.m_pregnancyChance = 0.66f;
		val4.m_pregnancyDuration = 90f;
		val4.m_offspring = cub;
		SetupBearRiding(val, val2, val3, component2);
		if (Log != null)
		{
			Log.LogInfo((object)"[nick008-bear] Early-configured Bjorn taming, breeding and Lox riding system.");
		}
		return true;
	}

	private IEnumerator WatchForCreatureDatabase()
	{
		while (true)
		{
			try
			{
				ZNetScene instance = ZNetScene.instance;
				ObjectDB instance2 = ObjectDB.instance;
				if ((Object)(object)instance != (Object)null && (Object)(object)instance2 != (Object)null && (Object)(object)instance.GetPrefab("Bjorn") != (Object)null && (Object)(object)instance.GetPrefab("Lox") != (Object)null && (Object)(object)instance2.GetItemPrefab("Honey") != (Object)null)
				{
					int instanceID = ((Object)instance).GetInstanceID();
					if (instanceID != configuredSceneId)
					{
						GameObject prefab = instance.GetPrefab("Bjorn");
						GameObject prefab2 = instance.GetPrefab("nick008_BearCub");
						if ((Object)(object)prefab != (Object)null && (Object)(object)prefab2 != (Object)null)
						{
							ConfigureFoodsOnPrefab(prefab, instance2);
							configuredSceneId = instanceID;
							Log.LogInfo((object)"[nick008-bear] Food setup completed.");
						}
					}
					if (configuredSceneId == instanceID)
					{
						UpdateLoadedBearFoods(instance2);
						GameObject val = EnsureDedicatedBearSaddle(instance2, instance);
						if ((Object)(object)val != (Object)null)
						{
							ItemDrop component = val.GetComponent<ItemDrop>();
							if ((Object)(object)component != (Object)null)
							{
								ApplyDedicatedBearSaddleToBears(instance, component);
							}
						}
						if ((Object)(object)Player.m_localPlayer != (Object)null)
						{
							RefreshLoadedBearSaddles(instance2);
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[nick008-bear] Setup watcher error: " + ex));
			}
			yield return (object)new WaitForSeconds(1f);
		}
	}

	private static bool IsBearTameable(Tameable tameable)
	{
		if ((Object)(object)tameable == (Object)null || (Object)(object)((Component)tameable).gameObject == (Object)null)
		{
			return false;
		}
		string text = ((Object)((Component)tameable).gameObject).name ?? string.Empty;
		return text.StartsWith("Bjorn", StringComparison.OrdinalIgnoreCase);
	}

	private static Component GetBearSaddleComponent(Tameable tameable)
	{
		if ((Object)(object)tameable == (Object)null)
		{
			return null;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
		FieldInfo field = typeof(Tameable).GetField("m_saddle", bindingAttr);
		if (field == null)
		{
			return null;
		}
		object? value = field.GetValue(tameable);
		return (Component)((value is Component) ? value : null);
	}

	private static bool TryInvokeBoolNoArgs(object instance, string methodName, out bool value)
	{
		value = false;
		if (instance == null)
		{
			return false;
		}
		try
		{
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			MethodInfo method = instance.GetType().GetMethod(methodName, bindingAttr, null, Type.EmptyTypes, null);
			if (method == null || method.ReturnType != typeof(bool))
			{
				return false;
			}
			object obj = method.Invoke(instance, null);
			if (obj is bool)
			{
				value = (bool)obj;
				return true;
			}
		}
		catch
		{
		}
		return false;
	}

	private static bool ReadHaveSaddleFromZdo(Tameable tameable, out bool haveSaddle)
	{
		haveSaddle = false;
		if ((Object)(object)tameable == (Object)null || (Object)(object)((Component)tameable).gameObject == (Object)null)
		{
			return false;
		}
		try
		{
			Component val = FindComponentByTypeName(((Component)tameable).gameObject, "ZNetView");
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			MethodInfo method = ((object)val).GetType().GetMethod("GetZDO", bindingAttr, null, Type.EmptyTypes, null);
			if (method == null)
			{
				return false;
			}
			object obj = method.Invoke(val, null);
			if (obj == null)
			{
				return false;
			}
			MethodInfo method2 = obj.GetType().GetMethod("GetBool", bindingAttr, null, new Type[2]
			{
				typeof(string),
				typeof(bool)
			}, null);
			MethodInfo method3 = obj.GetType().GetMethod("GetBool", bindingAttr, null, new Type[1] { typeof(string) }, null);
			string[] array = new string[4] { "HaveSaddle", "haveSaddle", "Saddle", "saddle" };
			for (int i = 0; i < array.Length; i++)
			{
				if (method2 != null)
				{
					object obj2 = method2.Invoke(obj, new object[2]
					{
						array[i],
						false
					});
					if (obj2 is bool && (bool)obj2)
					{
						haveSaddle = true;
						return true;
					}
				}
				if (method3 != null)
				{
					object obj3 = method3.Invoke(obj, new object[1] { array[i] });
					if (obj3 is bool && (bool)obj3)
					{
						haveSaddle = true;
						return true;
					}
				}
			}
			return true;
		}
		catch
		{
		}
		return false;
	}

	private static bool BearHasSaddle(Tameable tameable)
	{
		string[] array = new string[3] { "HaveSaddle", "HasSaddle", "IsSaddled" };
		bool value;
		for (int i = 0; i < array.Length; i++)
		{
			if (TryInvokeBoolNoArgs(tameable, array[i], out value) && value)
			{
				return true;
			}
		}
		if (ReadHaveSaddleFromZdo(tameable, out value) && value)
		{
			return true;
		}
		return false;
	}

	private static void ForceActiveHierarchy(GameObject root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return;
		}
		root.SetActive(true);
		Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] != (Object)null)
			{
				((Component)componentsInChildren[i]).gameObject.SetActive(true);
			}
		}
		Renderer[] componentsInChildren2 = root.GetComponentsInChildren<Renderer>(true);
		for (int j = 0; j < componentsInChildren2.Length; j++)
		{
			if ((Object)(object)componentsInChildren2[j] != (Object)null)
			{
				componentsInChildren2[j].enabled = true;
			}
		}
		Collider[] componentsInChildren3 = root.GetComponentsInChildren<Collider>(true);
		for (int k = 0; k < componentsInChildren3.Length; k++)
		{
			if ((Object)(object)componentsInChildren3[k] != (Object)null)
			{
				componentsInChildren3[k].enabled = true;
			}
		}
	}

	private static GameObject GetBearSaddleVisualObject(Tameable tameable)
	{
		if ((Object)(object)tameable == (Object)null || (Object)(object)((Component)tameable).gameObject == (Object)null)
		{
			return null;
		}
		int instanceID = ((Object)((Component)tameable).gameObject).GetInstanceID();
		if (saddleVisualCache.TryGetValue(instanceID, out var value))
		{
			if ((Object)(object)value != (Object)null)
			{
				return value;
			}
			saddleVisualCache.Remove(instanceID);
		}
		Transform val = FindVisualRoot(((Component)tameable).gameObject);
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		Transform val2 = FindChildRecursive(val, "nick008_BearSaddleVisual");
		if ((Object)(object)val2 != (Object)null)
		{
			saddleVisualCache[instanceID] = ((Component)val2).gameObject;
			return ((Component)val2).gameObject;
		}
		return null;
	}

	private static void SetBearSaddleVisual(Tameable tameable, bool haveSaddle)
	{
		Component bearSaddleComponent = GetBearSaddleComponent(tameable);
		GameObject bearSaddleVisualObject = GetBearSaddleVisualObject(tameable);
		if ((Object)(object)bearSaddleComponent != (Object)null && (Object)(object)bearSaddleComponent.gameObject != (Object)null)
		{
			try
			{
				PrepareBearSaddleRuntimeRefs(bearSaddleComponent, ((Object)(object)tameable != (Object)null) ? ((Component)tameable).gameObject : null);
				bearSaddleComponent.gameObject.SetActive(haveSaddle);
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogWarning((object)("[nick008-bear] Could not toggle logical bear saddle: " + ex.Message));
				}
			}
		}
		if (!((Object)(object)bearSaddleVisualObject != (Object)null))
		{
			return;
		}
		bearSaddleVisualObject.SetActive(haveSaddle);
		Renderer[] componentsInChildren = bearSaddleVisualObject.GetComponentsInChildren<Renderer>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] != (Object)null)
			{
				componentsInChildren[i].enabled = haveSaddle;
			}
		}
	}

	private static void SetFieldIfPresent(object instance, string fieldName, object value)
	{
		if (instance == null)
		{
			return;
		}
		try
		{
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = instance.GetType().GetField(fieldName, bindingAttr);
			if (field != null && (value == null || field.FieldType.IsInstanceOfType(value)))
			{
				field.SetValue(instance, value);
			}
		}
		catch
		{
		}
	}

	private static void PrepareBearSaddleRuntimeRefs(Component saddle, GameObject bear)
	{
		if ((Object)(object)saddle == (Object)null)
		{
			return;
		}
		if ((Object)(object)bear == (Object)null)
		{
			Tameable componentInParent = saddle.GetComponentInParent<Tameable>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				bear = ((Component)componentInParent).gameObject;
			}
		}
		if (!((Object)(object)bear == (Object)null))
		{
			SetFieldIfPresent(saddle, "m_character", bear.GetComponent<Character>());
			SetFieldIfPresent(saddle, "m_nview", bear.GetComponent<ZNetView>());
			SetFieldIfPresent(saddle, "m_tambable", bear.GetComponent<Tameable>());
			SetFieldIfPresent(saddle, "m_monsterAI", bear.GetComponent<MonsterAI>());
		}
	}

	private static Vector3 DivideVector(Vector3 a, Vector3 b)
	{
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3((Mathf.Abs(b.x) > 0.0001f) ? (a.x / b.x) : a.x, (Mathf.Abs(b.y) > 0.0001f) ? (a.y / b.y) : a.y, (Mathf.Abs(b.z) > 0.0001f) ? (a.z / b.z) : a.z);
	}

	private static GameObject EnsureBearSaddleVisual(Tameable tameable, ObjectDB db)
	{
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: 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_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: 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_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0305: Unknown result type (might be due to invalid IL or missing references)
		//IL_030a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0316: Unknown result type (might be due to invalid IL or missing references)
		//IL_031d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0322: Unknown result type (might be due to invalid IL or missing references)
		//IL_0336: Unknown result type (might be due to invalid IL or missing references)
		//IL_033b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0345: Unknown result type (might be due to invalid IL or missing references)
		//IL_034a: Unknown result type (might be due to invalid IL or missing references)
		//IL_034f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0359: Unknown result type (might be due to invalid IL or missing references)
		//IL_035e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0363: Unknown result type (might be due to invalid IL or missing references)
		//IL_0368: Unknown result type (might be due to invalid IL or missing references)
		//IL_0371: Unknown result type (might be due to invalid IL or missing references)
		//IL_041b: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)tameable == (Object)null || (Object)(object)((Component)tameable).gameObject == (Object)null || (Object)(object)db == (Object)null)
		{
			return null;
		}
		int instanceID = ((Object)((Component)tameable).gameObject).GetInstanceID();
		if (saddleVisualCache.TryGetValue(instanceID, out var value) && !((Object)(object)value != (Object)null))
		{
			saddleVisualCache.Remove(instanceID);
		}
		Transform val = FindVisualRoot(((Component)tameable).gameObject);
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		GameObject itemPrefab = db.GetItemPrefab("SaddleLox");
		if ((Object)(object)itemPrefab == (Object)null)
		{
			return null;
		}
		Transform val2 = FindChildRecursive(itemPrefab.transform, "attach");
		if ((Object)(object)val2 == (Object)null)
		{
			if (Log != null)
			{
				Log.LogError((object)"[nick008-bear] SaddleLox/attach was not found.");
			}
			return null;
		}
		Transform val3 = FindChildRecursive(((Component)tameable).gameObject.transform, "Spine_02");
		if ((Object)(object)val3 == (Object)null)
		{
			val3 = FindChildRecursive(((Component)tameable).gameObject.transform, "Chest");
		}
		if ((Object)(object)val3 == (Object)null)
		{
			val3 = FindChildRecursive(((Component)tameable).gameObject.transform, "Spine_01");
		}
		if ((Object)(object)val3 == (Object)null)
		{
			val3 = val;
		}
		Transform val4 = FindChildRecursive(val, "nick008_BearSaddleVisual");
		if ((Object)(object)val4 != (Object)null)
		{
			Transform transform = ((Component)tameable).gameObject.transform;
			val4.localScale = val2.localScale;
			val4.position = val3.position + transform.up * -0.05f + transform.forward * -0.15f + transform.right * 0.02f;
			Quaternion rotation = transform.rotation * val2.localRotation * Quaternion.Euler(270f, 0f, 90f) * Quaternion.AngleAxis(-90f, Vector3.forward) * Quaternion.AngleAxis(90f, Vector3.right);
			val4.rotation = rotation;
			saddleVisualCache[instanceID] = ((Component)val4).gameObject;
			return ((Component)val4).gameObject;
		}
		GameObject val5 = Object.Instantiate<GameObject>(((Component)val2).gameObject, val);
		((Object)val5).name = "nick008_BearSaddleVisual";
		Rigidbody[] componentsInChildren = val5.GetComponentsInChildren<Rigidbody>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
		}
		Collider[] componentsInChildren2 = val5.GetComponentsInChildren<Collider>(true);
		for (int j = 0; j < componentsInChildren2.Length; j++)
		{
			if ((Object)(object)componentsInChildren2[j] != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[j]);
			}
		}
		Vector3 localScale = val2.localScale;
		val5.transform.localScale = localScale;
		Transform transform2 = ((Component)tameable).gameObject.transform;
		val5.transform.position = val3.position + transform2.up * -0.05f + transform2.forward * -0.15f + transform2.right * 0.02f;
		Quaternion rotation2 = transform2.rotation * val2.localRotation * Quaternion.Euler(270f, 0f, 90f) * Quaternion.AngleAxis(-90f, Vector3.forward) * Quaternion.AngleAxis(90f, Vector3.right);
		val5.transform.rotation = rotation2;
		Renderer[] componentsInChildren3 = val5.GetComponentsInChildren<Renderer>(true);
		for (int k = 0; k < componentsInChildren3.Length; k++)
		{
			if ((Object)(object)componentsInChildren3[k] != (Object)null)
			{
				componentsInChildren3[k].enabled = true;
				((Component)componentsInChildren3[k]).gameObject.SetActive(true);
			}
		}
		val5.SetActive(false);
		saddleVisualCache[instanceID] = val5;
		if (Log != null)
		{
			Log.LogInfo((object)("[nick008-bear] Created ONE visual SaddleLox/attach clone for Bjorn id=" + instanceID + ", renderers=" + componentsInChildren3.Length + ", attachScale=" + localScale));
		}
		return val5;
	}

	private static void RefreshLoadedBearSaddles(ObjectDB db)
	{
		Tameable[] array = Object.FindObjectsOfType<Tameable>();
		foreach (Tameable tameable in array)
		{
			if (IsBearTameable(tameable))
			{
				bool flag = BearHasSaddle(tameable);
				if (flag)
				{
					EnsureBearSaddleVisual(tameable, db);
				}
				SetBearSaddleVisual(tameable, flag);
			}
		}
	}

	private static Sadle GetControlledBearSaddle(Player player)
	{
		if ((Object)(object)player == (Object)null)
		{
			return null;
		}
		try
		{
			IDoodadController doodadController = player.GetDoodadController();
			Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Character character = val.GetCharacter();
			if ((Object)(object)character == (Object)null || (Object)(object)((Component)character).gameObject == (Object)null)
			{
				return null;
			}
			Tameable component = ((Component)character).GetComponent<Tameable>();
			return IsBearTameable(component) ? val : null;
		}
		catch
		{
			return null;
		}
	}

	private static void RestoreLevel3MountedScale()
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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_004e: 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)
		try
		{
			if ((Object)(object)level3ScaledBear != (Object)null && (Object)(object)((Component)level3ScaledBear).gameObject != (Object)null)
			{
				((Component)level3ScaledBear).transform.localScale = level3OriginalLocalScale;
				if (Log != null)
				{
					ManualLogSource log = Log;
					Vector3 lossyScale = ((Component)level3ScaledBear).transform.lossyScale;
					log.LogInfo((object)("[nick008-bear] 1.1.4 FINAL: restored 2-star bear scale after dismount to " + ((Vector3)(ref lossyScale)).ToString("F2")));
				}
			}
		}
		catch
		{
		}
		finally
		{
			level3ScaledBear = null;
			level3OriginalLocalScale = Vector3.one;
		}
	}

	private static void ApplyLevel3MountedScale(Character mount)
	{
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)mount == (Object)null || mount.GetLevel() < 3)
			{
				RestoreLevel3MountedScale();
				return;
			}
			if ((Object)(object)level3ScaledBear != (Object)null && (Object)(object)level3ScaledBear != (Object)(object)mount)
			{
				RestoreLevel3MountedScale();
			}
			if ((Object)(object)level3ScaledBear == (Object)null)
			{
				level3ScaledBear = mount;
				level3OriginalLocalScale = ((Component)mount).transform.localScale;
				float x = ((Component)mount).transform.lossyScale.x;
				if (x > 1.251f)
				{
					float num = 1.25f / x;
					((Component)mount).transform.localScale = ((Component)mount).transform.localScale * num;
				}
				if (Log != null)
				{
					ManualLogSource log = Log;
					string text = ((Vector3)(ref level3OriginalLocalScale)).ToString("F2");
					Vector3 lossyScale = ((Component)mount).transform.lossyScale;
					log.LogInfo((object)("[nick008-bear] 1.1.4 FINAL: mounted level-3 bear scale " + text + " -> world " + ((Vector3)(ref lossyScale)).ToString("F2")));
				}
			}
		}
		catch (Exception ex)
		{
			if (Log != null)
			{
				Log.LogWarning((object)("[nick008-bear] 1.1.3 scale test failed: " + ex.Message));
			}
		}
	}

	private static void RunLevel3MovementFallback(Character mount)
	{
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: 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_0228: Unknown result type (might be due to invalid IL or missing references)
		//IL_0247: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if ((Object)(object)mount == (Object)null || ((Object)mount).GetInstanceID() != mountedBearControlId || mount.GetLevel() < 3 || Time.time - mountedBearControlTime > 0.2f || ((Vector3)(ref mountedBearDesiredDirection)).sqrMagnitude < 0.01f)
			{
				return;
			}
			Tameable component = ((Component)mount).GetComponent<Tameable>();
			Rigidbody val = null;
			FieldInfo fieldInfo = AccessTools.Field(typeof(Character), "m_body");
			if (fieldInfo != null)
			{
				object? value = fieldInfo.GetValue(mount);
				val = (Rigidbody)((value is Rigidbody) ? value : null);
			}
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)mount).GetComponent<Rigidbody>();
			}
			if (!IsBearTameable(component) || (Object)(object)val == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)mount).GetInstanceID();
			if (!mountedBearDiagnosticsLogged.Contains(instanceID))
			{
				mountedBearDiagnosticsLogged.Add(instanceID);
				if (Log != null)
				{
					ManualLogSource log = Log;
					object[] array = new object[14]
					{
						"[nick008-bear] 1.1.3 LEVEL3 DIAG: level=",
						mount.GetLevel(),
						", walk=",
						mount.m_walkSpeed.ToString("0.00"),
						", speed=",
						mount.m_speed.ToString("0.00"),
						", run=",
						mount.m_runSpeed.ToString("0.00"),
						", bodyKinematic=",
						val.isKinematic,
						", constraints=",
						val.constraints,
						", rootScale=",
						null
					};
					Vector3 lossyScale = ((Component)mount).transform.lossyScale;
					array[13] = ((Vector3)(ref lossyScale)).ToString("F2");
					log.LogInfo((object)string.Concat(array));
				}
			}
			Vector3 linearVelocity = val.linearVelocity;
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(linearVelocity.x, 0f, linearVelocity.z);
			if (!(((Vector3)(ref val2)).sqrMagnitude > 0.09f))
			{
				float num = (mountedBearWantsRun ? Mathf.Max(mount.m_runSpeed, 7f) : Mathf.Max(mount.m_speed, 3f));
				Vector3 val3 = ((Vector3)(ref mountedBearDesiredDirection)).normalized * num;
				linearVelocity.x = val3.x;
				linearVelocity.z = val3.z;
				val.linearVelocity = linearVelocity;
			}
		}
		catch (Exception ex)
		{
			if (Log != null)
			{
				Log.LogWarning((object)("[nick008-bear] 1.1.3 level3 Rigidbody fallback failed: " + ex.Message));
			}
		}
	}

	private void FixedUpdate()
	{
		try
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				RestoreLevel3MountedScale();
				return;
			}
			Sadle controlledBearSaddle = GetControlledBearSaddle(localPlayer);
			if ((Object)(object)controlledBearSaddle == (Object)null)
			{
				RestoreLevel3MountedScale();
				return;
			}
			Character character = controlledBearSaddle.GetCharacter();
			ApplyLevel3MountedScale(character);
			RunLevel3MovementFallback(character);
		}
		catch (Exception ex)
		{
			if (Log != null)
			{
				Log.LogWarning((object)("[nick008-bear] 1.1.3 plugin FixedUpdate fallback failed: " + ex.Message));
			}
		}
	}

	private static void ConfigureFoodsOnPrefab(GameObject bear, ObjectDB db)
	{
		if (!((Object)(object)bear == (Object)null) && !((Object)(object)db == (Object)null))
		{
			MonsterAI component = bear.GetComponent<MonsterAI>();
			if (!((Object)(object)component == (Object)null))
			{
				component.m_consumeItems = BuildFoodList(db);
				component.m_consumeRange = 1.8f;
				component.m_consumeSearchInterval = 10f;
				component.m_consumeSearchRange = 15f;
			}
		}
	}

	private static void UpdateLoadedBearFoods(ObjectDB db)
	{
		MonsterAI[] array = Object.FindObjectsOfType<MonsterAI>();
		foreach (MonsterAI val in array)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
			{
				string text = ((Object)((Component)val).gameObject).name ?? string.Empty;
				if (text.StartsWith("Bjorn", StringComparison.OrdinalIgnoreCase) && (val.m_consumeItems == null || val.m_consumeItems.Count == 0))
				{
					val.m_consumeItems = BuildFoodList(db);
					val.m_consumeRange = 1.8f;
					val.m_consumeSearchInterval = 10f;
					val.m_consumeSearchRange = 15f;
				}
			}
		}
	}

	private static List<ItemDrop> BuildFoodList(ObjectDB db)
	{
		List<ItemDrop> list = new List<ItemDrop>();
		for (int i = 0; i < FoodPrefabNames.Length; i++)
		{
			GameObject itemPrefab = db.GetItemPrefab(FoodPrefabNames[i]);
			if (!((Object)(object)itemPrefab == (Object)null))
			{
				ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null && !list.Contains(component))
				{
					list.Add(component);
				}
			}
		}
		return list;
	}

	private static GameObject EnsureDedicatedBearSaddle(ObjectDB db, ZNetScene scene)
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Expected O, but got Unknown
		if ((Object)(object)db == (Object)null || (Object)(object)scene == (Object)null || (Object)(object)Instance == (Object)null)
		{
			return null;
		}
		try
		{
			GameObject val = db.GetItemPrefab("nick008_BearSaddleItem");
			if ((Object)(object)val == (Object)null)
			{
				GameObject itemPrefab = db.GetItemPrefab("SaddleLox");
				if ((Object)(object)itemPrefab == (Object)null)
				{
					return null;
				}
				if ((Object)(object)Instance.customSaddlePrefabRoot == (Object)null)
				{
					Instance.customSaddlePrefabRoot = new GameObject("nick008_bear_saddle_prefab_root");
					Instance.customSaddlePrefabRoot.transform.SetParent(((Component)Instance).transform, false);
					Instance.customSaddlePrefabRoot.SetActive(false);
				}
				val = Object.Instantiate<GameObject>(itemPrefab, Instance.customSaddlePrefabRoot.transform);
				((Object)val).name = "nick008_BearSaddleItem";
				ItemDrop component = val.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val);
					Log.LogError((object)"[nick008-bear] Could not clone SaddleLox ItemDrop for Bear Saddle.");
					return null;
				}
				component.m_itemData.m_shared.m_name = "Bear Saddle";
				component.m_itemData.m_shared.m_description = "A sturdy saddle made for riding a tamed bear.";
				RegisterItemInObjectDB(db, val);
				RegisterPrefabInZNetScene(scene, val);
				Log.LogInfo((object)"[nick008-bear] 1.2.1 created dedicated Bear Saddle item from vanilla SaddleLox.");
			}
			else
			{
				RegisterPrefabInZNetScene(scene, val);
			}
			EnsureBearSaddleRecipe(db, scene, val);
			int instanceID = ((Object)db).GetInstanceID();
			if (customSaddleConfiguredDbId != instanceID)
			{
				customSaddleConfiguredDbId = instanceID;
				RefreshKnownRecipesForLocalPlayer();
			}
			return val;
		}
		catch (Exception ex)
		{
			Log.LogError((object)("[nick008-bear] 1.2.1 Bear Saddle registration failed: " + ex));
			return null;
		}
	}

	private static void RegisterItemInObjectDB(ObjectDB db, GameObject itemPrefab)
	{
		if (!((Object)(object)db == (Object)null) && !((Object)(object)itemPrefab == (Object)null))
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(ObjectDB), "m_items");
			IList list = ((fieldInfo != null) ? (fieldInfo.GetValue(db) as IList) : null);
			if (list != null && !list.Contains(itemPrefab))
			{
				list.Add(itemPrefab);
			}
			MethodInfo methodInfo = AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				methodInfo.Invoke(db, null);
			}
		}
	}

	private static void RegisterPrefabInZNetScene(ZNetScene scene, GameObject prefab)
	{
		if (!((Object)(object)scene == (Object)null) && !((Object)(object)prefab == (Object)null))
		{
			if (!scene.m_prefabs.Contains(prefab))
			{
				scene.m_prefabs.Add(prefab);
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(ZNetScene), "m_namedPrefabs");
			IDictionary dictionary = ((fieldInfo != null) ? (fieldInfo.GetValue(scene) as IDictionary) : null);
			if (dictionary != null)
			{
				int valheimStableHash = GetValheimStableHash("nick008_BearSaddleItem");
				dictionary[valheimStableHash] = prefab;
			}
		}
	}

	private static int GetValheimStableHash(string value)
	{
		try
		{
			Type type = AccessTools.TypeByName("StringExtensionMethods");
			if (type != null)
			{
				MethodInfo method = type.GetMethod("GetStableHashCode", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
				if (method != null)
				{
					return (int)method.Invoke(null, new object[1] { value });
				}
			}
		}
		catch
		{
		}
		int num = 5381;
		int num2 = num;
		for (int i = 0; i < value.Length; i += 2)
		{
			num = ((num << 5) + num) ^ value[i];
			if (i == value.Length - 1)
			{
				break;
			}
			num2 = ((num2 << 5) + num2) ^ value[i + 1];
		}
		return num + num2 * 1566083941;
	}

	private static void EnsureBearSaddleRecipe(ObjectDB db, ZNetScene scene, GameObject customPrefab)
	{
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Expected O, but got Unknown
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_0250: Expected O, but got Unknown
		//IL_0267: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: Expected O, but got Unknown
		if ((Object)(object)db == (Object)null || (Object)(object)scene == (Object)null || (Object)(object)customPrefab == (Object)null)
		{
			return;
		}
		FieldInfo fieldInfo = AccessTools.Field(typeof(ObjectDB), "m_recipes");
		IList list = ((fieldInfo != null) ? (fieldInfo.GetValue(db) as IList) : null);
		if (list == null)
		{
			Log.LogError((object)"[nick008-bear] ObjectDB.m_recipes was not found; Bear Saddle recipe cannot be added.");
			return;
		}
		for (int i = 0; i < list.Count; i++)
		{
			object? obj = list[i];
			Recipe val = (Recipe)((obj is Recipe) ? obj : null);
			if ((Object)(object)val != (Object)null && ((Object)val).name == "Recipe_nick008_BearSaddle")
			{
				return;
			}
		}
		ItemDrop component = customPrefab.GetComponent<ItemDrop>();
		GameObject val2 = ResolveItemPrefab(db, "BronzeNails");
		GameObject val3 = ResolveBearHidePrefab(db);
		GameObject val4 = ResolveItemPrefab(db, "FineWood");
		GameObject prefab = scene.GetPrefab("piece_workbench");
		ItemDrop val5 = (((Object)(object)val2 != (Object)null) ? val2.GetComponent<ItemDrop>() : null);
		ItemDrop val6 = (((Object)(object)val3 != (Object)null) ? val3.GetComponent<ItemDrop>() : null);
		ItemDrop val7 = (((Object)(object)val4 != (Object)null) ? val4.GetComponent<ItemDrop>() : null);
		CraftingStation val8 = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<CraftingStation>() : null);
		if ((Object)(object)component == (Object)null || (Object)(object)val5 == (Object)null || (Object)(object)val6 == (Object)null || (Object)(object)val7 == (Object)null || (Object)(object)val8 == (Object)null)
		{
			Log.LogWarning((object)("[nick008-bear] Bear Saddle recipe waiting for resources/station. BronzeNails=" + ((Object)(object)val5 != (Object)null) + ", BearHide=" + ((Object)(object)val6 != (Object)null) + ", FineWood=" + ((Object)(object)val7 != (Object)null) + ", Workbench=" + ((Object)(object)val8 != (Object)null)));
			return;
		}
		Recipe val9 = ScriptableObject.CreateInstance<Recipe>();
		((Object)val9).name = "Recipe_nick008_BearSaddle";
		val9.m_item = component;
		val9.m_amount = 1;
		Requirement[] array = (Requirement[])(object)new Requirement[3];
		Requirement val10 = new Requirement();
		val10.m_resItem = val5;
		val10.m_amount = 20;
		array[0] = val10;
		Requirement val11 = new Requirement();
		val11.m_resItem = val6;
		val11.m_amount = 5;
		array[1] = val11;
		Requirement val12 = new Requirement();
		val12.m_resItem = val7;
		val12.m_amount = 10;
		array[2] = val12;
		val9.m_resources = array;
		SetFieldIfPresent(val9, "m_craftingStation", val8);
		SetFieldIfPresent(val9, "m_minStationLevel", 1);
		SetFieldIfPresent(val9, "m_enabled", true);
		list.Add(val9);
		Log.LogInfo((object)("[nick008-bear] 1.2.1 Bear Saddle recipe added: 20 Bronze Nails + 5 " + ((Object)val3).name + " + 10 Fine Wood at Workbench."));
	}

	private static GameObject ResolveItemPrefab(ObjectDB db, params string[] prefabNames)
	{
		if ((Object)(object)db == (Object)null || prefabNames == null)
		{
			return null;
		}
		for (int i = 0; i < prefabNames.Length; i++)
		{
			GameObject itemPrefab = db.GetItemPrefab(prefabNames[i]);
			if ((Object)(object)itemPrefab != (Object)null)
			{
				return itemPrefab;
			}
		}
		return null;
	}

	private static GameObject ResolveBearHidePrefab(ObjectDB db)
	{
		GameObject val = ResolveItemPrefab(db, "BjornHide", "BearHide", "BjornPelt", "BearPelt", "BjornSkin", "BearSkin");
		if ((Object)(object)val != (Object)null)
		{
			return val;
		}
		FieldInfo fieldInfo = AccessTools.Field(typeof(ObjectDB), "m_items");
		IList list = ((fieldInfo != null) ? (fieldInfo.GetValue(db) as IList) : null);
		if (list == null)
		{
			return null;
		}
		for (int i = 0; i < list.Count; i++)
		{
			object? obj = list[i];
			GameObject val2 = (GameObject)((obj is GameObject) ? obj : null);
			if (!((Object)(object)val2 == (Object)null))
			{
				ItemDrop component = val2.GetComponent<ItemDrop>();
				string text = ((((Object)val2).name != null) ? ((Object)val2).name.ToLowerInvariant() : string.Empty);
				string text2 = (((Object)(object)component != (Object)null && component.m_itemData != null && component.m_itemData.m_shared != null && component.m_itemData.m_shared.m_name != null) ? component.m_itemData.m_shared.m_name.ToLowerInvariant() : string.Empty);
				bool flag = text.Contains("bjorn") || text.Contains("bear") || text2.Contains("bjorn") || text2.Contains("bear");
				bool flag2 = text.Contains("hide") || text.Contains("pelt") || text.Contains("skin") || text2.Contains("hide") || text2.Contains("pelt") || text2.Contains("skin");
				if (flag && flag2)
				{
					Log.LogInfo((object)("[nick008-bear] Bear hide auto-detected as prefab '" + ((Object)val2).name + "'."));
					return val2;
				}
			}
		}
		return null;
	}

	private static void ApplyDedicatedBearSaddleToBears(ZNetScene scene, ItemDrop bearSaddleItem)
	{
		if ((Object)(object)scene == (Object)null || (Object)(object)bearSaddleItem == (Object)null)
		{
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
		FieldInfo field = typeof(Tameable).GetField("m_saddleItem", bindingAttr);
		if (field == null)
		{
			return;
		}
		GameObject prefab = scene.GetPrefab("Bjorn");
		Tameable val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Tameable>() : null);
		if ((Object)(object)val != (Object)null)
		{
			field.SetValue(val, bearSaddleItem);
		}
		Tameable[] array = Object.FindObjectsOfType<Tameable>();
		for (int i = 0; i < array.Length; i++)
		{
			if (IsBearTameable(array[i]))
			{
				field.SetValue(array[i], bearSaddleItem);
			}
		}
	}

	private static void RefreshKnownRecipesForLocalPlayer()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		string[] array = new string[2] { "UpdateKnownRecipesList", "UpdateKnownRecipes" };
		for (int i = 0; i < array.Length; i++)
		{
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Player), array[i], (Type[])null, (Type[])null);
				if (methodInfo != null && methodInfo.GetParameters().Length == 0)
				{
					methodInfo.Invoke(localPlayer, null);
					break;
				}
			}
			catch
			{
			}
		}
	}

	private static bool SetupBearRiding(GameObject bear, GameObject lox, Tameable bearTame, Tameable loxTame)
	{
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: 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_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0196: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b7: 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_0337: Unknown result type (might be due to invalid IL or missing references)
		//IL_0340: Unknown result type (might be due to invalid IL or missing references)
		//IL_0349: Unknown result type (might be due to invalid IL or missing references)
		//IL_0317: Unknown result type (might be due to invalid IL or missing references)
		//IL_031e: Expected O, but got Unknown
		//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0421: 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)
		try
		{
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = typeof(Tameable).GetField("m_saddleItem", bindingAttr);
			FieldInfo field2 = typeof(Tameable).GetField("m_saddle", bindingAttr);
			if (field == null || field2 == null)
			{
				Log.LogError((object)"[nick008-bear] Tameable saddle fields were not found.");
				return false;
			}
			object? value = field2.GetValue(loxTame);
			Component val = (Component)((value is Component) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				val = FindComponentByTypeName(lox, "Sadle");
			}
			if ((Object)(object)val == (Object)null)
			{
				Log.LogError((object)"[nick008-bear] Vanilla Lox Sadle component was not found.");
				return false;
			}
			Transform val2 = FindVisualRoot(bear);
			if ((Object)(object)val2 == (Object)null)
			{
				Log.LogError((object)"[nick008-bear] Bjorn Visual root was not found.");
				return false;
			}
			Transform val3 = FindChildRecursive(bear.transform, "Spine_02");
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = FindChildRecursive(bear.transform, "Chest");
			}
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = FindChildRecursive(bear.transform, "Spine_01");
			}
			if ((Object)(object)val3 == (Object)null)
			{
				val3 = val2;
			}
			Transform transform = bear.transform;
			Vector3 position = val3.position + transform.up * -0.1f + transform.forward * 1.2f + transform.right * 0.6f;
			Quaternion rotation = transform.rotation;
			Vector3 position2 = val3.position + transform.up * 0.55f + transform.forward * 0.3f + transform.right * 0.05f;
			Transform val4 = FindChildRecursive(bear.transform, "nick008_BearSaddle");
			Component val5 = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponent(((object)val).GetType()) : null);
			if ((Object)(object)val5 == (Object)null)
			{
				GameObject val6 = Object.Instantiate<GameObject>(val.gameObject, bear.transform);
				((Object)val6).name = "nick008_BearSaddle";
				val6.SetActive(false);
				Renderer[] componentsInChildren = val6.GetComponentsInChildren<Renderer>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] != (Object)null)
					{
						Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
					}
				}
				val5 = val6.GetComponent(((object)val).GetType());
				if ((Object)(object)val5 == (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val6);
					Log.LogError((object)"[nick008-bear] Lox Sadel clone lost its Sadle component.");
					return false;
				}
			}
			val5.transform.SetParent(bear.transform, true);
			val5.transform.position = position;
			val5.transform.rotation = rotation;
			val5.transform.localScale = Vector3.one;
			SetFieldIfPresent(val5, "m_maxUseRange", 12f);
			SetFieldIfPresent(val5, "m_hoverText", "Bear Saddle");
			Transform val7 = FindChildRecursive(bear.transform, "nick008_BearMountPoint");
			if ((Object)(object)val7 == (Object)null)
			{
				GameObject val8 = new GameObject("nick008_BearMountPoint");
				val7 = val8.transform;
			}
			val7.SetParent(bear.transform, true);
			val7.position = position2;
			val7.rotation = rotation;
			val7.localScale = Vector3.one;
			SetFieldIfPresent(val5, "m_attachPoint", val7);
			PrepareBearSaddleRuntimeRefs(val5, bear);
			field.SetValue(bearTame, field.GetValue(loxTame));
			field2.SetValue(bearTame, val5);
			Collider[] componentsInChildren2 = val5.GetComponentsInChildren<Collider>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				if ((Object)(object)componentsInChildren2[j] != (Object)null)
				{
					componentsInChildren2[j].enabled = false;
				}
			}
			Log.LogInfo((object)("[nick008-bear] 1.1.4 FINAL riding setup. disabled logical saddle colliders=" + componentsInChildren2.Length + ", logical saddle distance from bear root=" + Vector3.Distance(bear.transform.position, val5.transform.position).ToString("0.00") + "m, rider mountPoint distance=" + Vector3.Distance(bear.transform.position, val7.position).ToString("0.00") + "m, colliders=" + componentsInChildren2.Length));
			return true;
		}
		catch (Exception ex)
		{
			Log.LogError((object)("[nick008-bear] Bear riding setup failed: " + ex));
			return false;
		}
	}

	private static Transform FindVisualRoot(GameObject creature)
	{
		if ((Object)(object)creature == (Object)null)
		{
			return null;
		}
		Transform val = creature.transform.Find("Visual");
		if (!((Object)(object)val != (Object)null))
		{
			return creature.transform;
		}
		return val;
	}

	private static Component FindComponentByTypeName(GameObject root, string typeName)
	{
		if ((Object)(object)root == (Object)null)
		{
			return null;
		}
		Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
		foreach (Component val in componentsInChildren)
		{
			if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == typeName)
			{
				return val;
			}
		}
		return null;
	}

	private static Transform FindChildRecursive(Transform root, string wantedName)
	{
		if ((Object)(object)root == (Object)null)
		{
			return null;
		}
		Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == wantedName)
			{
				return componentsInChildren[i];
			}
		}
		return null;
	}

	private static float CalculateSizeRatio(Transform bearVisual, Transform loxVisual)
	{
		float rendererHeight = GetRendererHeight(bearVisual);
		float rendererHeight2 = GetRendererHeight(loxVisual);
		if (rendererHeight > 0.1f && rendererHeight2 > 0.1f)
		{
			return Mathf.Clamp(rendererHeight / rendererHeight2, 0.45f, 0.85f);
		}
		return 0.65f;
	}

	private static float GetRendererHeight(Transform root)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
		bool flag = false;
		Bounds val = default(Bounds);
		foreach (Renderer val2 in componentsInChildren)
		{
			if ((Object)(object)val2 == (Object)null)
			{
				continue;
			}
			string text = ((Object)((Component)val2).gameObject).name ?? string.Empty;
			if (text.IndexOf("saddle", StringComparison.OrdinalIgnoreCase) < 0)
			{
				if (!flag)
				{
					val = val2.bounds;
					flag = true;
				}
				else
				{
					((Bounds)(ref val)).Encapsulate(val2.bounds);
				}
			}
		}
		if (!flag)
		{
			return 0f;
		}
		return ((Bounds)(ref val)).size.y;
	}

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

	private static void CopyPublicFields(Component destination, Component source)
	{
		if ((Object)(object)destination == (Object)null || (Object)(object)source == (Object)null)
		{
			return;
		}
		BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public;
		FieldInfo[] fields = ((object)source).GetType().GetFields(bindingAttr);
		Type type = ((object)destination).GetType();
		foreach (FieldInfo fieldInfo in fields)
		{
			FieldInfo field = type.GetField(fieldInfo.Name, bindingAttr);
			if (!(field == null) && !field.IsInitOnly && (field.FieldType.IsAssignableFrom(fieldInfo.FieldType) || fieldInfo.FieldType.IsAssignableFrom(field.FieldType)))
			{
				try
				{
					field.SetValue(destination, fieldInfo.GetValue(source));
				}
				catch
				{
				}
			}
		}
	}
}
[HarmonyPatch]
internal static class BearCubButcherProtectionPatch
{
	private const string CubPrefabName = "nick008_BearCub";

	private static bool loggedBlockedHit;

	private static MethodBase TargetMethod()
	{
		MethodInfo[] methods = typeof(Character).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (!(methodInfo.Name != "Damage"))
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 1 && parameters[0].ParameterType.Name == "HitData")
				{
					return methodInfo;
				}
			}
		}
		return null;
	}

	[HarmonyPrefix]
	private static bool Prefix(Character __instance, object __0)
	{
		try
		{
			if (!IsCub(__instance) || !IsButcherKnifeHit(__0))
			{
				return true;
			}
			if (!loggedBlockedHit && Nick008TameableBearPlugin.Log != null)
			{
				loggedBlockedHit = true;
				Nick008TameableBearPlugin.Log.LogInfo((object)"[nick008tameablebear] Protected bear cub from butcher-knife hit.");
			}
			return false;
		}
		catch
		{
			return true;
		}
	}

	private static bool IsCub(Character character)
	{
		if ((Object)(object)character == (Object)null || (Object)(object)((Component)character).gameObject == (Object)null)
		{
			return false;
		}
		string text = ((Object)((Component)character).gameObject).name ?? string.Empty;
		if (!text.Equals("nick008_BearCub", StringComparison.OrdinalIgnoreCase) && !text.StartsWith("nick008_BearCub(", StringComparison.OrdinalIgnoreCase))
		{
			return text.StartsWith("nick008_BearCub ", StringComparison.OrdinalIgnoreCase);
		}
		return true;
	}

	private static bool IsButcherKnifeHit(object hit)
	{
		if (hit == null)
		{
			return false;
		}
		object obj = InvokeNoArgMethod(hit, "GetAttacker");
		if (obj == null || !IsTypeOrBaseNamed(obj.GetType(), "Player"))
		{
			return false;
		}
		object obj2 = InvokeNoArgMethod(obj, "GetCurrentWeapon");
		if (obj2 == null)
		{
			return false;
		}
		object fieldValue = GetFieldValue(obj2, "m_dropPrefab");
		GameObject val = (GameObject)((fieldValue is GameObject) ? fieldValue : null);
		if ((Object)(object)val != (Object)null && LooksLikeButcherKnife(((Object)val).name))
		{
			return true;
		}
		object fieldValue2 = GetFieldValue(obj2, "m_shared");
		object fieldValue3 = GetFieldValue(fieldValue2, "m_name");
		if (fieldValue3 != null && LooksLikeButcherKnife(fieldValue3.ToString()))
		{
			return true;
		}
		return LooksLikeButcherKnife(obj2.ToString());
	}

	private static bool LooksLikeButcherKnife(string value)
	{
		if (string.IsNullOrEmpty(value))
		{
			return false;
		}
		string text = value.ToLowerInvariant();
		if (!text.Contains("butcher") && !text.Contains("knifebutcher"))
		{
			return text.Contains("butcherknife");
		}
		return true;
	}

	private static bool IsTypeOrBaseNamed(Type type, string name)
	{
		Type type2 = type;
		while (type2 != null)
		{
			if (string.Equals(type2.Name, name, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			type2 = type2.BaseType;
		}
		return false;
	}

	private static object InvokeNoArgMethod(object instance, string methodName)
	{
		if (instance == null)
		{
			return null;
		}
		Type type = instance.GetType();
		while (type != null)
		{
			MethodInfo method = type.GetMethod(methodName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (method != null)
			{
				return method.Invoke(instance, null);
			}
			type = type.BaseType;
		}
		return null;
	}

	private static object GetFieldValue(object instance, string fieldName)
	{
		if (instance == null)
		{
			return null;
		}
		Type type = instance.GetType();
		while (type != null)
		{
			FieldInfo field = type.GetField(fieldName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field.GetValue(instance);
			}
			type = type.BaseType;
		}
		return null;
	}
}