Decompiled source of RideableDrakes v1.0.0

BepInEx/plugins/RideableDrakes/RideableDrakes.dll

Decompiled 13 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;

[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("torubaki")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RideableDrakes")]
[assembly: AssemblyTitle("RideableDrakes")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace RideableDrakes
{
	internal static class RiderCamera
	{
		internal static DrakeMount Mount
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !((Character)Player.m_localPlayer).IsAttached() || ((Character)Player.m_localPlayer).IsDead())
				{
					return null;
				}
				return Player.m_localPlayer.GetDoodadController() as DrakeMount;
			}
		}

		internal static Vector3 Anchor(DrakeMount mount)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			return ((Component)mount).transform.TransformPoint(new Vector3(0f, 2.1f, 0.6f)) + Vector3.up;
		}
	}
	[HarmonyPatch(typeof(GameCamera), "GetCameraPosition")]
	internal static class RiderCameraLookPatch
	{
		private static readonly Action<Player> RefreshLook = AccessTools.MethodDelegate<Action<Player>>(AccessTools.Method(typeof(Player), "UpdateEyeRotation", (Type[])null, (Type[])null), (object)null, true);

		private static void Prefix()
		{
			if (Object.op_Implicit((Object)(object)RiderCamera.Mount))
			{
				RefreshLook(Player.m_localPlayer);
			}
		}
	}
	[HarmonyPatch(typeof(GameCamera), "GetOffsetedEyePos")]
	internal static class RiderCameraPositionPatch
	{
		private static readonly Func<GameCamera, Player, Vector3> CameraOffset = AccessTools.MethodDelegate<Func<GameCamera, Player, Vector3>>(AccessTools.Method(typeof(GameCamera), "GetCameraOffset", (Type[])null, (Type[])null), (object)null, true);

		private static bool Prefix(GameCamera __instance, ref Vector3 __result)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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)
			DrakeMount mount = RiderCamera.Mount;
			if (!Object.op_Implicit((Object)(object)mount))
			{
				return true;
			}
			__result = RiderCamera.Anchor(mount) + CameraOffset(__instance, Player.m_localPlayer);
			return false;
		}
	}
	[HarmonyPatch(typeof(GameCamera), "CollideRay2")]
	internal static class RiderCameraCollisionPatch
	{
		private static void Prefix(ref Vector3 eyePos)
		{
			//IL_0010: 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)
			DrakeMount mount = RiderCamera.Mount;
			if (Object.op_Implicit((Object)(object)mount))
			{
				eyePos = RiderCamera.Anchor(mount);
			}
		}
	}
	[HarmonyPatch(typeof(GameCamera), "ApplyCameraTilt")]
	internal static class RiderCameraTiltPatch
	{
		private static bool Prefix(Player player, ref Quaternion rot)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!Object.op_Implicit((Object)(object)RiderCamera.Mount))
			{
				return true;
			}
			rot = Quaternion.LookRotation(((Character)player).m_eye.forward, Vector3.up);
			return false;
		}
	}
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	internal static class CreatureRegistration
	{
		internal const string PrefabName = "TamedDrake";

		internal static GameObject Root;

		private static void Postfix(ZNetScene __instance, Dictionary<int, GameObject> ___m_namedPrefabs)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			GameObject prefab = __instance.GetPrefab("Hatchling");
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				Plugin.Log.LogError((object)"Hatchling prefab missing; TamedDrake could not be registered.");
				return;
			}
			if (Object.op_Implicit((Object)(object)Root))
			{
				Object.Destroy((Object)(object)Root);
			}
			Root = new GameObject("RideableDrakes_Prefabs");
			Root.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)Root);
			GameObject val = Object.Instantiate<GameObject>(prefab, Root.transform, false);
			((Object)val).name = "TamedDrake";
			val.transform.localScale = prefab.transform.localScale * Plugin.Scale.Value;
			Character component = val.GetComponent<Character>();
			component.m_name = "Tamed Drake";
			component.m_faction = (Faction)0;
			component.m_flying = true;
			component.m_disableWhileSleeping = false;
			BaseAI[] components = val.GetComponents<BaseAI>();
			for (int i = 0; i < components.Length; i++)
			{
				((Behaviour)components[i]).enabled = false;
			}
			Tameable[] components2 = val.GetComponents<Tameable>();
			for (int i = 0; i < components2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components2[i]);
			}
			Procreation[] components3 = val.GetComponents<Procreation>();
			for (int i = 0; i < components3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components3[i]);
			}
			Rigidbody component2 = val.GetComponent<Rigidbody>();
			component2.useGravity = false;
			component2.interpolation = (RigidbodyInterpolation)1;
			component2.collisionDetectionMode = (CollisionDetectionMode)2;
			ZSyncTransform component3 = val.GetComponent<ZSyncTransform>();
			component3.m_syncPosition = true;
			component3.m_syncRotation = true;
			component3.m_syncScale = true;
			component3.m_syncBodyVelocity = true;
			AttachSaddle(val, __instance.GetPrefab("SaddleAsksvin"));
			val.AddComponent<DrakeMount>();
			val.AddComponent<FlightController>();
			val.SetActive(true);
			__instance.m_prefabs.Add(val);
			___m_namedPrefabs.Add(StringExtensionMethods.GetStableHashCode("TamedDrake"), val);
			ItemRegistration.Register(__instance, Root.transform, ___m_namedPrefabs);
		}

		internal static void AttachSaddle(GameObject drake, GameObject saddleItem)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			MeshFilter componentInChildren = saddleItem.GetComponentInChildren<MeshFilter>(true);
			GameObject val = new GameObject("DrakeSaddle");
			val.layer = ((Component)drake.GetComponentInChildren<SkinnedMeshRenderer>(true)).gameObject.layer;
			val.AddComponent<MeshFilter>().sharedMesh = componentInChildren.sharedMesh;
			((Renderer)val.AddComponent<MeshRenderer>()).sharedMaterials = ((Renderer)((Component)componentInChildren).GetComponent<MeshRenderer>()).sharedMaterials;
			val.transform.SetParent(drake.transform, false);
			val.transform.localPosition = new Vector3(0f, 1.4f, 0.05f);
			val.transform.localRotation = Quaternion.Euler(-70f, 0f, 0f);
			val.transform.localScale = Vector3.one * 0.6f;
			val.transform.SetParent(Utils.FindChild(drake.transform, "Spine1", (IterativeSearchType)0), true);
			drake.GetComponentInChildren<Animator>(true).cullingMode = (AnimatorCullingMode)0;
			Transform transform = new GameObject("DrakeSeat").transform;
			transform.SetParent(val.transform, false);
			transform.localPosition = new Vector3(0f, 0.3f, -0.05f);
		}
	}
	public sealed class DrakeMount : MonoBehaviour, Interactable, Hoverable, IDoodadController, TextReceiver
	{
		private const string Request = "RD_Request";

		private const string Response = "RD_Response";

		private const string Release = "RD_Release";

		private const string RiderKey = "RD_Rider";

		private const string Rename = "RD_Rename";

		private const int NameLimit = 32;

		private const float UseRange = 6f;

		private ZNetView view;

		private Character character;

		private FlightController flight;

		private Transform seat;

		private float requestedAt = -100f;

		private float grantedAt = -100f;

		private float lastInput;

		private bool granted;

		private bool wasOwner;

		private float staminaRegenTimer;

		private float raiseSkillTimer;

		private const string ExhaustedKey = "RD_Exhausted";

		internal ZDOID Rider
		{
			get
			{
				//IL_001a: 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)
				if (!Object.op_Implicit((Object)(object)view) || !view.IsValid())
				{
					return ZDOID.None;
				}
				return view.GetZDO().GetZDOID("RD_Rider");
			}
		}

		internal bool Exhausted => view.GetZDO().GetBool("RD_Exhausted", false);

		internal float RiderSkill
		{
			get
			{
				if (!IsLocalRider() || (object)Player.m_localPlayer.GetDoodadController() != this)
				{
					return 0f;
				}
				return ((Character)Player.m_localPlayer).GetSkills().GetSkillFactor((SkillType)110);
			}
		}

		public float GetMaxStamina()
		{
			return Plugin.MaxStamina.Value;
		}

		public float GetStamina()
		{
			if (!Object.op_Implicit((Object)(object)view) || !view.IsValid())
			{
				return 0f;
			}
			return Mathf.Clamp(view.GetZDO().GetFloat(ZDOVars.s_stamina, GetMaxStamina()), 0f, GetMaxStamina());
		}

		internal void UpdateFlightStamina(float dt, bool grounded, bool sprinting)
		{
			float num = GetStamina();
			staminaRegenTimer -= dt;
			if (!grounded)
			{
				float num2 = Plugin.FlightStaminaDrain.Value + (sprinting ? Plugin.SprintStaminaDrain.Value : 0f);
				num = Mathf.Max(0f, num - num2 * Mathf.Lerp(1f, 0.5f, RiderSkill) * dt);
				staminaRegenTimer = 1f;
				if (num <= 0f)
				{
					view.GetZDO().Set("RD_Exhausted", true);
				}
			}
			else
			{
				if (staminaRegenTimer <= 0f)
				{
					num = Mathf.Min(GetMaxStamina(), num + Plugin.StaminaRegen.Value * (2f - num / GetMaxStamina()) * dt);
				}
				if (num > 0f)
				{
					view.GetZDO().Set("RD_Exhausted", false);
				}
			}
			view.GetZDO().Set(ZDOVars.s_stamina, num);
			if (IsLocalRider() && sprinting && !Exhausted)
			{
				raiseSkillTimer += dt;
				if (raiseSkillTimer > 1f)
				{
					raiseSkillTimer = 0f;
					((Character)Player.m_localPlayer).RaiseSkill((SkillType)110, 1f);
				}
			}
			else
			{
				raiseSkillTimer = 0f;
			}
		}

		private void Awake()
		{
			view = ((Component)this).GetComponent<ZNetView>();
			character = ((Component)this).GetComponent<Character>();
			flight = ((Component)this).GetComponent<FlightController>();
			seat = Utils.FindChild(((Component)this).transform, "DrakeSeat", (IterativeSearchType)0);
			view.Register<ZDOID>("RD_Request", (Action<long, ZDOID>)RequestControl);
			view.Register<bool>("RD_Response", (Action<long, bool>)ControlResponse);
			view.Register<ZDOID>("RD_Release", (Action<long, ZDOID>)ReleaseControl);
			view.Register<string, ZDOID>("RD_Rename", (Action<long, string, ZDOID>)RenameDrake);
		}

		public string GetHoverName()
		{
			return character.GetHoverName();
		}

		public float GetHoverOffset()
		{
			return 0f;
		}

		public string GetHoverText()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (IsLocalRider())
			{
				return "";
			}
			string text = GetHoverName() + "\n[<color=yellow><b>$KEY_Use</b></color>] " + ((Rider != ZDOID.None) ? "In use" : "Mount");
			if (Rider == ZDOID.None)
			{
				text += ((ZInput.IsNonClassicFunctionality() && ZInput.IsGamepadActive()) ? "\n[<color=yellow><b>$KEY_AltKeys + $KEY_Use</b></color>] $hud_rename" : "\n[<color=yellow><b>$KEY_AltPlace + $KEY_Use</b></color>] $hud_rename");
			}
			return Localization.instance.Localize(text);
		}

		public bool Interact(Humanoid user, bool repeat, bool alt)
		{
			//IL_0046: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if (!repeat)
			{
				Player val = (Player)(object)((user is Player) ? user : null);
				if (val != null && IsValid())
				{
					if ((object)val.GetDoodadController() == this)
					{
						val.StopDoodadControl();
						return true;
					}
					if (((Character)val).IsAttached() || val.GetDoodadController() != null || ((Character)val).IsDead() || Vector3.Distance(((Component)val).transform.position, seat.position) > 6f)
					{
						return false;
					}
					if (alt)
					{
						if (Rider != ZDOID.None)
						{
							return false;
						}
						TextInput.instance.RequestText((TextReceiver)(object)this, "$hud_rename", 32);
						return true;
					}
					requestedAt = Time.time;
					view.InvokeRPC("RD_Request", new object[1] { ((Character)val).GetZDOID() });
					return true;
				}
			}
			return false;
		}

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

		public void SetText(string text)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (IsValid() && Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead())
			{
				view.InvokeRPC("RD_Rename", new object[2]
				{
					text ?? "",
					((Character)localPlayer).GetZDOID()
				});
			}
		}

		private void RenameDrake(long sender, string name, ZDOID playerID)
		{
			//IL_0023: 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_003a: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			if (!IsValid() || !view.IsOwner() || !character.IsTamed() || Rider != ZDOID.None)
			{
				return;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(playerID);
			if (zDO != null && zDO.GetOwner() == sender && !(Vector3.Distance(zDO.GetPosition(), seat.position) > 6f))
			{
				name = StringExtensionMethods.RemoveRichTextTags(name ?? "").Replace('\n', ' ').Replace('\r', ' ')
					.Replace('\t', ' ')
					.Trim();
				if (name.Length > 32)
				{
					name = name.Substring(0, 32);
				}
				view.GetZDO().Set(ZDOVars.s_overrideHoverName, name);
			}
		}

		private void RequestControl(long sender, ZDOID playerID)
		{
			//IL_0020: 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_003f: 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_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)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			if (view.IsOwner() && !character.IsDead())
			{
				ZDO zDO = ZDOMan.instance.GetZDO(playerID);
				if (zDO != null && zDO.GetOwner() == sender && Vector3.Distance(zDO.GetPosition(), seat.position) <= 6f && (Rider == ZDOID.None || Rider == playerID))
				{
					view.GetZDO().Set("RD_Rider", playerID);
					lastInput = Time.time;
					flight.ClearInput();
					view.InvokeRPC(sender, "RD_Response", new object[1] { true });
					view.GetZDO().SetOwner(sender);
				}
				else
				{
					view.InvokeRPC(sender, "RD_Response", new object[1] { false });
				}
			}
		}

		private void ControlResponse(long sender, bool allowed)
		{
			if (!(Time.time - requestedAt > 5f))
			{
				granted = allowed;
				grantedAt = Time.time;
				if (!allowed && Object.op_Implicit((Object)(object)Player.m_localPlayer))
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_inuse", 0, (Sprite)null, false);
				}
			}
		}

		private void FixedUpdate()
		{
			//IL_0072: 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_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_01a8: 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_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: 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_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			if (!view.IsValid())
			{
				DetachLocalRider();
				return;
			}
			if (view.IsOwner() && !wasOwner)
			{
				lastInput = Time.time;
			}
			wasOwner = view.IsOwner();
			Player localPlayer = Player.m_localPlayer;
			if (granted && Object.op_Implicit((Object)(object)localPlayer) && view.IsOwner() && Rider == ((Character)localPlayer).GetZDOID())
			{
				granted = false;
				if (((Character)localPlayer).IsDead() || ((Character)localPlayer).IsAttached() || localPlayer.GetDoodadController() != null)
				{
					view.InvokeRPC("RD_Release", new object[1] { ((Character)localPlayer).GetZDOID() });
					return;
				}
				localPlayer.StartDoodadControl((IDoodadController)(object)this);
				((Character)localPlayer).AttachStart(seat, ((Component)this).gameObject, true, false, false, "attach_asksvin", new Vector3(1.8f, 0.5f, 0f), (Transform)null);
				lastInput = Time.time;
			}
			if (granted && Time.time - grantedAt > 5f)
			{
				granted = false;
			}
			if (Object.op_Implicit((Object)(object)localPlayer) && (object)localPlayer.GetDoodadController() == this && (character.IsDead() || ((Character)localPlayer).IsDead() || !((Character)localPlayer).IsAttached() || Rider != ((Character)localPlayer).GetZDOID() || !view.IsOwner()))
			{
				localPlayer.StopDoodadControl();
			}
			if (view.IsOwner() && !(Rider == ZDOID.None))
			{
				ZDO zDO = ZDOMan.instance.GetZDO(Rider);
				if (zDO == null || Vector3.Distance(zDO.GetPosition(), seat.position) > 12f || Time.time - lastInput > 5f)
				{
					view.GetZDO().Set("RD_Rider", ZDOID.None);
					flight.ClearInput();
					DetachLocalRider();
				}
			}
		}

		internal void CaptureControls(Vector3 move, bool run, float vertical)
		{
			//IL_0027: 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 (IsLocalRider() && view.IsOwner())
			{
				lastInput = Time.time;
				flight.SetInput(Mathf.Clamp(move.z, -1f, 1f), Mathf.Clamp(move.x, -1f, 1f), vertical, run);
			}
		}

		private void ReleaseControl(long sender, ZDOID playerID)
		{
			//IL_000e: 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)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (view.IsOwner() && !(Rider != playerID) && ((ZDOID)(ref playerID)).UserID == sender)
			{
				view.GetZDO().Set("RD_Rider", ZDOID.None);
				flight.ClearInput();
			}
		}

		private bool IsLocalRider()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer))
			{
				return Rider == ((Character)Player.m_localPlayer).GetZDOID();
			}
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		public void ApplyControlls(Vector3 moveDir, Vector3 lookDir, bool run, bool autoRun, bool block)
		{
		}

		public Component GetControlledComponent()
		{
			return (Component)(object)character;
		}

		public Vector3 GetPosition()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return seat.position;
		}

		public bool IsValid()
		{
			if (Object.op_Implicit((Object)(object)this) && Object.op_Implicit((Object)(object)view) && view.IsValid())
			{
				return !character.IsDead();
			}
			return false;
		}

		public void OnUseStop(Player player)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			((Character)player).AttachStop();
			if (Object.op_Implicit((Object)(object)view) && view.IsValid())
			{
				view.InvokeRPC("RD_Release", new object[1] { ((Character)player).GetZDOID() });
			}
			if (Object.op_Implicit((Object)(object)flight))
			{
				flight.ClearInput();
			}
		}

		internal void DetachLocalRider()
		{
			Player localPlayer = Player.m_localPlayer;
			if (Object.op_Implicit((Object)(object)localPlayer) && (object)localPlayer.GetDoodadController() == this)
			{
				((Character)localPlayer).AttachStop();
				localPlayer.StopDoodadControl();
			}
		}

		private void OnDestroy()
		{
			DetachLocalRider();
		}
	}
	public sealed class DrakeTaming : MonoBehaviour, Interactable
	{
		internal const string TamedKey = "RD_Tamed";

		internal const string UntilKey = "RD_SedatedUntil";

		internal const string GroundKey = "RD_Grounded";

		private const string ClaimKey = "RD_Tamer";

		private const string ClaimUntilKey = "RD_ClaimUntil";

		private const string DropKey = "RD_SaddleDropped";

		private const string Request = "RD_TameRequest";

		private const long Duration = 100000000L;

		private ZNetView view;

		private Character character;

		private MonsterAI ai;

		private Rigidbody body;

		private CapsuleCollider capsule;

		private Faction wildFaction;

		private bool configured;

		private bool suppressed;

		private bool aiWasEnabled;

		private bool gravity;

		private RigidbodyConstraints wildConstraints;

		private long requestedUntil;

		private int mask;

		private static readonly FieldInfo CurrentAttack = AccessTools.Field(typeof(Humanoid), "m_currentAttack");

		private long Now => ZNet.instance.GetTime().Ticks;

		internal bool Permanent
		{
			get
			{
				if (Object.op_Implicit((Object)(object)view) && view.IsValid())
				{
					return view.GetZDO().GetBool("RD_Tamed", false);
				}
				return false;
			}
		}

		internal bool Sedated
		{
			get
			{
				if (Object.op_Implicit((Object)(object)view) && view.IsValid() && !Permanent)
				{
					return view.GetZDO().GetLong("RD_SedatedUntil", 0L) > Now;
				}
				return false;
			}
		}

		internal bool Grounded
		{
			get
			{
				if (Sedated)
				{
					return view.GetZDO().GetBool("RD_Grounded", false);
				}
				return false;
			}
		}

		private void Awake()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			view = ((Component)this).GetComponent<ZNetView>();
			character = ((Component)this).GetComponent<Character>();
			ai = ((Component)this).GetComponent<MonsterAI>();
			body = ((Component)this).GetComponent<Rigidbody>();
			capsule = ((Component)this).GetComponent<CapsuleCollider>();
			wildFaction = character.m_faction;
			mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" });
			if (Object.op_Implicit((Object)(object)view) && view.IsValid())
			{
				view.Register<ZDOID>("RD_TameRequest", (Action<long, ZDOID>)RequestTame);
				if (Object.op_Implicit((Object)(object)((Component)this).GetComponent<DrakeMount>()) && view.IsOwner())
				{
					view.GetZDO().Set("RD_Tamed", true);
				}
				if (Permanent)
				{
					ConfigureMount();
				}
			}
		}

		internal void Tranquilize()
		{
			if (view.IsValid() && view.IsOwner() && !character.IsDead() && !character.IsTamed() && !Permanent && !Sedated)
			{
				view.GetZDO().Set("RD_SedatedUntil", Now + 100000000);
				view.GetZDO().Set("RD_Grounded", false);
				Suppress();
			}
		}

		private void Suppress()
		{
			//IL_00b3: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			if (!suppressed)
			{
				aiWasEnabled = Object.op_Implicit((Object)(object)ai) && ((Behaviour)ai).enabled;
				gravity = body.useGravity;
				wildConstraints = body.constraints;
				suppressed = true;
			}
			if (Object.op_Implicit((Object)(object)ai))
			{
				((BaseAI)ai).StopMoving();
				((Behaviour)ai).enabled = false;
			}
			Character obj = character;
			Humanoid val = (Humanoid)(object)((obj is Humanoid) ? obj : null);
			if (val != null)
			{
				object? value = CurrentAttack.GetValue(val);
				object? obj2 = ((value is Attack) ? value : null);
				if (obj2 != null)
				{
					((Attack)obj2).Stop();
				}
				CurrentAttack.SetValue(val, null);
			}
			character.m_faction = (Faction)0;
			body.useGravity = false;
			body.collisionDetectionMode = (CollisionDetectionMode)2;
		}

		private void FixedUpdate()
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)view) || !view.IsValid() || character.IsDead())
			{
				return;
			}
			if (view.IsOwner() && !Permanent && Object.op_Implicit((Object)(object)((Component)this).GetComponent<DrakeMount>()))
			{
				view.GetZDO().Set("RD_Tamed", true);
			}
			if (Permanent)
			{
				if (!configured)
				{
					ConfigureMount();
				}
				return;
			}
			if (Sedated)
			{
				Suppress();
			}
			else if (suppressed)
			{
				suppressed = false;
				character.m_faction = wildFaction;
				body.useGravity = gravity;
				body.constraints = wildConstraints;
				if (Object.op_Implicit((Object)(object)ai))
				{
					((Behaviour)ai).enabled = aiWasEnabled;
				}
				if (view.IsOwner())
				{
					view.GetZDO().Set("RD_Grounded", false);
				}
			}
			if (requestedUntil > Now && view.IsOwner() && Object.op_Implicit((Object)(object)Player.m_localPlayer) && view.GetZDO().GetZDOID("RD_Tamer") == ((Character)Player.m_localPlayer).GetZDOID())
			{
				CompleteTame();
			}
		}

		internal void Step(float dt)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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_019a: 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_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: 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_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: 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_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			Suppress();
			body.angularVelocity = Vector3.zero;
			if (view.GetZDO().GetBool("RD_Grounded", false))
			{
				body.linearVelocity = Vector3.zero;
				body.constraints = (RigidbodyConstraints)126;
				return;
			}
			Vector3 val = Vector3.MoveTowards(body.linearVelocity, Vector3.down * 3f, 12f * dt);
			val.x = (val.z = 0f);
			Bounds bounds = ((Collider)capsule).bounds;
			float num = float.PositiveInfinity;
			RaycastHit[] array = Physics.RaycastAll(new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).min.y + 1f, ((Bounds)(ref bounds)).center.z), Vector3.down, 5f, mask, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val2 = array[i];
				if (!((Component)((RaycastHit)(ref val2)).collider).transform.IsChildOf(((Component)this).transform) && ((RaycastHit)(ref val2)).normal.y > 0.35f)
				{
					num = Mathf.Min(num, ((Bounds)(ref bounds)).min.y - ((RaycastHit)(ref val2)).point.y);
				}
			}
			bool flag = num < 0.08f;
			if (!float.IsPositiveInfinity(num))
			{
				val.y = Mathf.Max(val.y, (num < 0f) ? Mathf.Min((0f - num) * 4f, 2f) : ((0f - num) / dt));
			}
			float num2 = float.PositiveInfinity;
			RaycastHit val3 = default(RaycastHit);
			if (val.y < 0f)
			{
				array = body.SweepTestAll(Vector3.down, (0f - val.y) * dt + 0.05f, (QueryTriggerInteraction)1);
				for (int i = 0; i < array.Length; i++)
				{
					RaycastHit val4 = array[i];
					if ((mask & (1 << ((Component)((RaycastHit)(ref val4)).collider).gameObject.layer)) != 0 && !((Component)((RaycastHit)(ref val4)).collider).transform.IsChildOf(((Component)this).transform) && ((RaycastHit)(ref val4)).distance < num2)
					{
						num2 = ((RaycastHit)(ref val4)).distance;
						val3 = val4;
					}
				}
			}
			if (!float.IsPositiveInfinity(num2))
			{
				if (((RaycastHit)(ref val3)).normal.y > 0.35f)
				{
					val.y = (0f - Mathf.Max(0f, ((RaycastHit)(ref val3)).distance - 0.02f)) / dt;
					flag |= ((RaycastHit)(ref val3)).distance < 0.08f;
				}
				else
				{
					val = Vector3.ProjectOnPlane(val, ((RaycastHit)(ref val3)).normal);
				}
			}
			if (flag && val.y < 0f)
			{
				val.y = 0f;
			}
			view.GetZDO().Set("RD_Grounded", flag);
			body.linearVelocity = val;
			if (flag)
			{
				body.constraints = (RigidbodyConstraints)126;
			}
			character.GetZAnim().SetBool("flying", true);
			character.GetZAnim().SetFloat("forward_speed", 0f);
		}

		internal string HoverText()
		{
			if (!Sedated)
			{
				return null;
			}
			if (!Grounded)
			{
				return "Drake\nTranquilized — descending";
			}
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || Saddle(localPlayer) == null)
			{
				return "Drake\nTranquilized — requires Drake Saddle";
			}
			return Localization.instance.Localize("Drake\n[<color=yellow><b>$KEY_Use</b></color>] Attach Drake Saddle");
		}

		private static ItemData Saddle(Player player)
		{
			return ((Humanoid)player).GetInventory().GetItem("Drake Saddle", -1, false);
		}

		public bool Interact(Humanoid user, bool repeat, bool alt)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (Permanent)
			{
				return ((Component)this).GetComponent<DrakeMount>()?.Interact(user, repeat, alt) ?? false;
			}
			if (!(repeat || alt))
			{
				Player val = (Player)(object)((user is Player) ? user : null);
				if (val != null && Grounded && Saddle(val) != null && !((Character)val).IsDead() && !(Vector3.Distance(((Component)val).transform.position, ((Component)this).transform.position) > 6f))
				{
					requestedUntil = Now + 50000000;
					view.InvokeRPC("RD_TameRequest", new object[1] { ((Character)val).GetZDOID() });
					return true;
				}
			}
			return false;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			object obj;
			if (item == null)
			{
				obj = null;
			}
			else
			{
				GameObject dropPrefab = item.m_dropPrefab;
				obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
			}
			if ((string?)obj == "DrakeSaddle")
			{
				return Interact(user, repeat: false, alt: false);
			}
			return false;
		}

		private void RequestTame(long sender, ZDOID playerID)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if (view.IsOwner() && Grounded && !character.IsDead())
			{
				ZDO zDO = view.GetZDO();
				ZDO zDO2 = ZDOMan.instance.GetZDO(playerID);
				if (zDO2 != null && zDO2.GetOwner() == sender && !(Vector3.Distance(zDO2.GetPosition(), ((Component)this).transform.position) > 6f) && zDO.GetLong("RD_ClaimUntil", 0L) <= Now)
				{
					zDO.Set("RD_Tamer", playerID);
					zDO.Set("RD_ClaimUntil", Now + 50000000);
					zDO.SetOwner(sender);
				}
			}
		}

		private void CompleteTame()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			requestedUntil = 0L;
			Player localPlayer = Player.m_localPlayer;
			ItemData val = Saddle(localPlayer);
			if (Grounded && !((Character)localPlayer).IsDead() && val != null && !(Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position) > 6f) && ((Humanoid)localPlayer).GetInventory().RemoveItem(val, 1))
			{
				view.GetZDO().Set("RD_Tamed", true);
				character.SetTamed(true);
				ConfigureMount();
			}
		}

		private void ConfigureMount()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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)
			configured = true;
			if (suppressed)
			{
				body.constraints = wildConstraints;
			}
			if (view.IsOwner())
			{
				view.GetZDO().Persistent = true;
			}
			character.m_name = "Tamed Drake";
			character.m_faction = (Faction)0;
			character.m_flying = true;
			character.m_disableWhileSleeping = false;
			if (Object.op_Implicit((Object)(object)ai))
			{
				((Behaviour)ai).enabled = false;
			}
			if (view.IsOwner())
			{
				character.SetTamed(true);
			}
			if (!Object.op_Implicit((Object)(object)((Component)this).GetComponent<DrakeMount>()))
			{
				GameObject prefab = ZNetScene.instance.GetPrefab("TamedDrake");
				((Component)this).transform.localScale = prefab.transform.localScale;
				Transform val = Utils.FindChild(prefab.transform, "DrakeSaddle", (IterativeSearchType)0);
				((Object)Object.Instantiate<GameObject>(((Component)val).gameObject, Utils.FindChild(((Component)this).transform, "Spine1", (IterativeSearchType)0), false)).name = ((Object)val).name;
				((Component)this).GetComponentInChildren<Animator>(true).cullingMode = (AnimatorCullingMode)0;
				((Component)this).gameObject.AddComponent<FlightController>();
				((Component)this).gameObject.AddComponent<DrakeMount>();
			}
			body.useGravity = false;
			body.interpolation = (RigidbodyInterpolation)1;
			body.collisionDetectionMode = (CollisionDetectionMode)2;
			ZSyncTransform component = ((Component)this).GetComponent<ZSyncTransform>();
			component.m_syncPosition = (component.m_syncRotation = (component.m_syncScale = (component.m_syncBodyVelocity = true)));
		}

		internal void DropSaddle()
		{
			//IL_0073: 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)
			if (Object.op_Implicit((Object)(object)view) && view.IsValid() && view.IsOwner() && Permanent && !view.GetZDO().GetBool("RD_SaddleDropped", false))
			{
				view.GetZDO().Set("RD_SaddleDropped", true);
				Object.Instantiate<GameObject>(ZNetScene.instance.GetPrefab("DrakeSaddle"), character.GetCenterPoint(), Quaternion.identity).GetComponent<ItemDrop>().m_itemData.m_stack = 1;
			}
		}
	}
	[HarmonyPatch(typeof(Character), "Awake")]
	internal static class DrakeTamingSpawn
	{
		private static void Postfix(Character __instance)
		{
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			if (Object.op_Implicit((Object)(object)component) && component.IsValid())
			{
				int prefab = component.GetZDO().GetPrefab();
				if ((prefab == StringExtensionMethods.GetStableHashCode("Hatchling") || prefab == StringExtensionMethods.GetStableHashCode("TamedDrake")) && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<DrakeTaming>()))
				{
					((Component)__instance).gameObject.AddComponent<DrakeTaming>();
				}
			}
		}
	}
	[HarmonyPatch(typeof(Character), "OnDeath")]
	internal static class DrakeSaddleRecovery
	{
		private static void Prefix(Character __instance)
		{
			((Component)__instance).GetComponent<DrakeTaming>()?.DropSaddle();
		}
	}
	public sealed class FlightController : MonoBehaviour
	{
		private Rigidbody body;

		private CapsuleCollider capsule;

		private Character character;

		private ZSyncAnimation animationSync;

		private DrakeMount mount;

		private float forward;

		private float turn;

		private float vertical;

		private bool sprint;

		private int solidMask;

		private readonly RaycastHit[] hits = (RaycastHit[])(object)new RaycastHit[32];

		internal bool Grounded { get; private set; }

		private void Awake()
		{
			body = ((Component)this).GetComponent<Rigidbody>();
			capsule = ((Component)this).GetComponent<CapsuleCollider>();
			character = ((Component)this).GetComponent<Character>();
			animationSync = ((Component)this).GetComponent<ZSyncAnimation>();
			mount = ((Component)this).GetComponent<DrakeMount>();
			solidMask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "terrain", "vehicle" });
		}

		internal void SetInput(float forwardInput, float turnInput, float verticalInput, bool fast)
		{
			forward = forwardInput;
			turn = turnInput;
			vertical = verticalInput;
			sprint = fast;
		}

		internal void ClearInput()
		{
			SetInput(0f, 0f, 0f, fast: false);
		}

		internal void Step(float dt)
		{
			//IL_0037: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: 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_015d: 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_0170: 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_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: 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_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: 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_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			if (!character.IsTamed())
			{
				character.SetTamed(true);
			}
			character.m_flying = true;
			body.useGravity = false;
			body.angularVelocity = Vector3.zero;
			if (!Object.op_Implicit((Object)(object)mount))
			{
				mount = ((Component)this).GetComponent<DrakeMount>();
			}
			bool num = mount.Rider != ZDOID.None;
			Grounded = GroundGap(Vector3.zero, 0f, 0f) <= 0.15f;
			bool flag = num && sprint && Mathf.Abs(forward) > 0.01f;
			mount.UpdateFlightStamina(dt, Grounded, flag);
			bool flag2 = !num || mount.Exhausted;
			float num2 = ((!flag2) ? turn : 0f) * Plugin.TurnSpeed.Value * dt;
			Quaternion val = body.rotation * Quaternion.Euler(0f, num2, 0f);
			body.MoveRotation(val);
			float num3 = (flag ? (Plugin.SprintSpeed.Value * (1f + mount.RiderSkill * 0.25f)) : Plugin.Speed.Value);
			Vector3 val2 = val * Vector3.forward * (forward * num3);
			val2.y = vertical * Plugin.VerticalSpeed.Value;
			if (flag2)
			{
				val2 = Vector3.down * 5f;
			}
			float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
			Vector3 linearVelocity = body.linearVelocity;
			bool flag3 = sqrMagnitude < ((Vector3)(ref linearVelocity)).sqrMagnitude || Vector3.Dot(val2, body.linearVelocity) < 0f;
			Vector3 velocity = Vector3.MoveTowards(body.linearVelocity, val2, (flag3 ? Plugin.Deceleration.Value : Plugin.Acceleration.Value) * dt);
			float num4 = ((flag2 || vertical < 0f || (Grounded && vertical <= 0f)) ? 0f : Plugin.HoverHeight.Value);
			MaintainClearance(ref velocity, dt, num4);
			float num5 = ((Vector3)(ref velocity)).magnitude * dt;
			RaycastHit val3 = default(RaycastHit);
			if (num5 > 0f && body.SweepTest(((Vector3)(ref velocity)).normalized, ref val3, num5 + 0.1f, (QueryTriggerInteraction)1))
			{
				float num6 = Vector3.Dot(velocity, ((RaycastHit)(ref val3)).normal);
				if (num6 < 0f && (num4 > 0f || ((RaycastHit)(ref val3)).normal.y <= 0.35f || velocity.y >= 0f))
				{
					velocity -= ((RaycastHit)(ref val3)).normal * num6;
				}
			}
			body.linearVelocity = velocity;
			animationSync.SetBool("flying", true);
			animationSync.SetBool("onGround", false);
			animationSync.SetBool("inWater", false);
			animationSync.SetFloat("forward_speed", Vector3.Dot(velocity, ((Component)this).transform.forward));
			animationSync.SetFloat("sideway_speed", 0f);
			animationSync.SetFloat("turn_speed", flag2 ? 0f : turn);
		}

		private void MaintainClearance(ref Vector3 velocity, float dt, float clearance)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			float num = GroundGap(velocity, dt, clearance);
			if (!float.IsPositiveInfinity(num))
			{
				float num2 = ((num < clearance) ? Mathf.Min((clearance - num) * 4f, Plugin.VerticalSpeed.Value) : ((clearance - num) / dt));
				velocity.y = Mathf.Max(velocity.y, num2);
			}
		}

		private float GroundGap(Vector3 velocity, float dt, float clearance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0051: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = ((Collider)capsule).bounds;
			float num = Mathf.Max(0.1f, Mathf.Min(((Bounds)(ref bounds)).extents.x, ((Bounds)(ref bounds)).extents.z) * 0.8f);
			int num2 = Physics.SphereCastNonAlloc(new Vector3(((Bounds)(ref bounds)).center.x + velocity.x * dt, ((Bounds)(ref bounds)).min.y + clearance + num + 0.25f, ((Bounds)(ref bounds)).center.z + velocity.z * dt), num, Vector3.down, hits, clearance * 2f + Mathf.Max(0f, (0f - velocity.y) * dt) + 2f, solidMask, (QueryTriggerInteraction)1);
			float num3 = float.NegativeInfinity;
			for (int i = 0; i < num2; i++)
			{
				if (!((Component)((RaycastHit)(ref hits[i])).collider).transform.IsChildOf(((Component)this).transform) && !(((RaycastHit)(ref hits[i])).normal.y < 0.35f))
				{
					num3 = Mathf.Max(num3, ((RaycastHit)(ref hits[i])).point.y);
				}
			}
			return ((Bounds)(ref bounds)).min.y - num3;
		}
	}
	internal static class ItemRegistration
	{
		internal const string Dart = "TranquilizerDart";

		internal const string Saddle = "DrakeSaddle";

		internal static void Register(ZNetScene scene, Transform root, Dictionary<int, GameObject> prefabs)
		{
			Add(scene, root, prefabs, "ArrowNeedle", "TranquilizerDart", "Tranquilizer Dart", "Ooze beneath a needle's point stills even the fury of the mountain winds.");
			Add(scene, root, prefabs, "SaddleAsksvin", "DrakeSaddle", "Drake Saddle", "Silver bindings and supple leather, for those who would bridle the mountain wind.");
			Populate(ObjectDB.instance);
		}

		private static void Add(ZNetScene scene, Transform root, Dictionary<int, GameObject> prefabs, string source, string name, string title, string description)
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(scene.GetPrefab(source), root, false);
			((Object)val).name = name;
			ItemData itemData = val.GetComponent<ItemDrop>().m_itemData;
			itemData.m_dropPrefab = val;
			itemData.m_shared.m_name = title;
			itemData.m_shared.m_description = description;
			itemData.m_shared.m_maxQuality = 1;
			if (name == "TranquilizerDart")
			{
				itemData.m_shared.m_damages = default(DamageTypes);
				itemData.m_shared.m_damagesPerLevel = default(DamageTypes);
				itemData.m_shared.m_attackForce = 0f;
				itemData.m_shared.m_attackStatusEffect = null;
			}
			val.SetActive(true);
			scene.m_prefabs.Add(val);
			prefabs.Add(StringExtensionMethods.GetStableHashCode(name), val);
		}

		internal static void Populate(ObjectDB db)
		{
			if (Object.op_Implicit((Object)(object)db) && Object.op_Implicit((Object)(object)ZNetScene.instance) && Object.op_Implicit((Object)(object)db.GetItemPrefab("Needle")))
			{
				AddRecipe(db, "TranquilizerDart", 20, new string[3] { "Needle", "Feathers", "Ooze" }, new int[3] { 4, 2, 2 });
				AddRecipe(db, "DrakeSaddle", 1, new string[3] { "LeatherScraps", "FineWood", "Silver" }, new int[3] { 20, 15, 10 });
				AccessTools.Method(typeof(ObjectDB), "UpdateRegisters", (Type[])null, (Type[])null).Invoke(db, null);
			}
		}

		private static void AddRecipe(ObjectDB db, string name, int amount, string[] resources, int[] counts)
		{
			GameObject prefab = ZNetScene.instance.GetPrefab(name);
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				return;
			}
			db.m_items.RemoveAll((GameObject p) => !Object.op_Implicit((Object)(object)p) || (((Object)p).name == name && (Object)(object)p != (Object)(object)prefab));
			if (!db.m_items.Contains(prefab))
			{
				db.m_items.Add(prefab);
			}
			Recipe val = ((IEnumerable<Recipe>)db.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => Object.op_Implicit((Object)(object)r) && ((Object)r).name == "Recipe_" + name));
			if (Object.op_Implicit((Object)(object)val))
			{
				val.m_item = prefab.GetComponent<ItemDrop>();
				return;
			}
			Recipe val2 = ScriptableObject.CreateInstance<Recipe>();
			((Object)val2).name = "Recipe_" + name;
			val2.m_item = prefab.GetComponent<ItemDrop>();
			val2.m_amount = amount;
			val2.m_craftingStation = ZNetScene.instance.GetPrefab("piece_workbench").GetComponent<CraftingStation>();
			val2.m_resources = ((IEnumerable<string>)resources).Select((Func<string, int, Requirement>)((string r, int i) => new Requirement
			{
				m_resItem = db.GetItemPrefab(r).GetComponent<ItemDrop>(),
				m_amount = counts[i],
				m_amountPerLevel = 0
			})).ToArray();
			db.m_recipes.Add(val2);
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ItemDatabaseAwake
	{
		private static void Postfix(ObjectDB __instance)
		{
			ItemRegistration.Populate(__instance);
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	internal static class ItemDatabaseCopy
	{
		private static void Postfix(ObjectDB __instance)
		{
			ItemRegistration.Populate(__instance);
		}
	}
	[HarmonyPatch(typeof(Projectile), "Setup")]
	internal static class DartProjectile
	{
		internal static readonly int Marker = StringExtensionMethods.GetStableHashCode("RD_Tranquilizer");

		private static void Prefix(HitData hitData, ItemData ammo)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (ammo == null)
			{
				obj = null;
			}
			else
			{
				GameObject dropPrefab = ammo.m_dropPrefab;
				obj = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
			}
			if (!((string?)obj != "TranquilizerDart") && hitData != null)
			{
				hitData.m_damage = default(DamageTypes);
				hitData.m_pushForce = 0f;
				hitData.m_statusEffectHash = Marker;
				hitData.m_healthReturn = (hitData.m_eitrAdd = 0f);
			}
		}
	}
	[HarmonyPatch(typeof(Character), "RPC_Damage")]
	internal static class DartImpact
	{
		private static bool Prefix(Character __instance, HitData hit)
		{
			if (hit.m_statusEffectHash != DartProjectile.Marker)
			{
				return true;
			}
			DrakeTaming component = ((Component)__instance).GetComponent<DrakeTaming>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.Tranquilize();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Hud), "UpdateMount")]
	internal static class DrakeMountHudPatch
	{
		private static bool Prefix(Hud __instance, Player player)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			if (!(player.GetDoodadController() is DrakeMount drakeMount) || !drakeMount.IsValid())
			{
				return true;
			}
			Character val = (Character)drakeMount.GetControlledComponent();
			__instance.m_mountPanel.SetActive(true);
			__instance.m_mountIcon.overrideSprite = ZNetScene.instance.GetPrefab("DrakeSaddle").GetComponent<ItemDrop>().m_itemData.GetIcon();
			__instance.m_mountHealthBarSlow.SetValue(val.GetHealthPercentage());
			__instance.m_mountHealthBarFast.SetValue(val.GetHealthPercentage());
			((TMP_Text)__instance.m_mountHealthText).text = Mathf.CeilToInt(val.GetHealth()).ToString();
			__instance.m_mountStaminaBar.SetValue(drakeMount.GetStamina() / drakeMount.GetMaxStamina());
			((TMP_Text)__instance.m_mountStaminaText).text = Mathf.CeilToInt(drakeMount.GetStamina()).ToString();
			((TMP_Text)__instance.m_mountNameText).text = Localization.instance.Localize(val.GetHoverName());
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "AttachStop")]
	internal static class DrakeDismountRotation
	{
		private static void Prefix(Player __instance, out bool __state)
		{
			__state = __instance.GetDoodadController() is DrakeMount || (Object.op_Implicit((Object)(object)__instance.GetAttachPoint()) && Object.op_Implicit((Object)(object)((Component)__instance.GetAttachPoint()).GetComponentInParent<DrakeMount>()));
		}

		private static void Postfix(Player __instance, bool __state)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if (__state && !((Character)__instance).IsAttached())
			{
				Quaternion rotation = Quaternion.Euler(0f, ((Component)__instance).transform.eulerAngles.y, 0f);
				((Component)__instance).transform.rotation = rotation;
				Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>();
				component.rotation = rotation;
				component.angularVelocity = Vector3.zero;
			}
		}
	}
	[HarmonyPatch(typeof(EnemyHud), "TestShow")]
	internal static class RiddenDrakeHudPatch
	{
		private static bool Prefix(Character c, ref bool __result)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!Object.op_Implicit((Object)(object)localPlayer) || !(localPlayer.GetDoodadController() is DrakeMount drakeMount) || (Object)(object)drakeMount.GetControlledComponent() != (Object)(object)c)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(Character), "UpdateMotion")]
	internal static class FlightMotionPatch
	{
		private static bool Prefix(Character __instance, float dt)
		{
			DrakeTaming component = ((Component)__instance).GetComponent<DrakeTaming>();
			if (Object.op_Implicit((Object)(object)component) && component.Sedated && !__instance.IsDead())
			{
				component.Step(dt);
				return false;
			}
			FlightController flightController = default(FlightController);
			if (!((Component)__instance).TryGetComponent<FlightController>(ref flightController) || __instance.IsDead())
			{
				return true;
			}
			flightController.Step(dt);
			return false;
		}
	}
	[HarmonyPatch(typeof(Character), "GetHoverText")]
	internal static class HoverPatch
	{
		private static bool Prefix(Character __instance, ref string __result)
		{
			DrakeTaming component = ((Component)__instance).GetComponent<DrakeTaming>();
			string text = (Object.op_Implicit((Object)(object)component) ? component.HoverText() : null);
			if (text != null)
			{
				__result = text;
				return false;
			}
			DrakeMount drakeMount = default(DrakeMount);
			if (!((Component)__instance).TryGetComponent<DrakeMount>(ref drakeMount))
			{
				return true;
			}
			__result = drakeMount.GetHoverText();
			return false;
		}
	}
	[HarmonyPatch(typeof(Player), "SetControls")]
	internal static class RiderInputPatch
	{
		private static readonly Func<PlayerController, bool, bool> TakeInput = AccessTools.MethodDelegate<Func<PlayerController, bool, bool>>(AccessTools.Method(typeof(PlayerController), "TakeInput", (Type[])null, (Type[])null), (object)null, true);

		private static readonly Func<PlayerController, bool> InInventory = AccessTools.MethodDelegate<Func<PlayerController, bool>>(AccessTools.Method(typeof(PlayerController), "InInventoryEtc", (Type[])null, (Type[])null), (object)null, true);

		private static void Prefix(Player __instance, ref Vector3 movedir, ref bool jump, ref bool crouch, ref bool run, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, ref bool dodge, ref bool block, ref bool blockHold, ref bool autoRun)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && __instance.GetDoodadController() is DrakeMount drakeMount)
			{
				PlayerController component = ((Component)__instance).GetComponent<PlayerController>();
				bool flag = Object.op_Implicit((Object)(object)component) && TakeInput(component, arg2: false) && !InInventory(component) && !Hud.InRadial();
				float vertical = (flag ? (((ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump")) ? 1f : 0f) - ((ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch")) ? 1f : 0f)) : 0f);
				drakeMount.CaptureControls(flag ? movedir : Vector3.zero, flag & run, vertical);
				jump = (crouch = (run = (attack = (attackHold = (secondaryAttack = (secondaryAttackHold = (dodge = (block = (blockHold = (autoRun = false))))))))));
				movedir = Vector3.zero;
			}
		}
	}
	[BepInPlugin("torubaki.rideabledrakes", "Rideable Drakes", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		internal static ConfigEntry<float> Scale;

		internal static ConfigEntry<float> Speed;

		internal static ConfigEntry<float> SprintSpeed;

		internal static ConfigEntry<float> Acceleration;

		internal static ConfigEntry<float> Deceleration;

		internal static ConfigEntry<float> TurnSpeed;

		internal static ConfigEntry<float> VerticalSpeed;

		internal static ConfigEntry<float> HoverHeight;

		internal static ConfigEntry<float> MaxStamina;

		internal static ConfigEntry<float> FlightStaminaDrain;

		internal static ConfigEntry<float> SprintStaminaDrain;

		internal static ConfigEntry<float> StaminaRegen;

		private Harmony patches;

		private void Awake()
		{
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Scale = Setting("Creature", "Scale", 1.5f, 0.5f, 3f, "Size multiplier; restart the world after changing.");
			Speed = Setting("Flight", "Speed", 10f, 1f, 40f, "Normal flight speed (m/s).");
			SprintSpeed = Setting("Flight", "SprintSpeed", 18f, 1f, 60f, "Fast flight speed (m/s).");
			Acceleration = Setting("Flight", "Acceleration", 8f, 1f, 40f, "Acceleration (m/s squared).");
			Deceleration = Setting("Flight", "Deceleration", 10f, 1f, 40f, "Braking strength (m/s squared).");
			TurnSpeed = Setting("Flight", "TurnSpeed", 100f, 10f, 240f, "Turning speed (degrees/s).");
			VerticalSpeed = Setting("Flight", "VerticalSpeed", 6f, 1f, 20f, "Ascent and descent speed (m/s).");
			HoverHeight = Setting("Flight", "HoverHeight", 1.2f, 0.3f, 5f, "Clearance below the body collider (m).");
			MaxStamina = Setting("Stamina", "MaxStamina", 100f, 1f, 1000f, "Mount stamina capacity.");
			FlightStaminaDrain = Setting("Stamina", "FlightDrain", 2f, 0.1f, 100f, "Stamina per second whenever airborne, including hovering and unoccupied descent.");
			SprintStaminaDrain = Setting("Stamina", "SprintDrain", 10f, 0.1f, 100f, "Additional stamina per second while sprinting in the air.");
			StaminaRegen = Setting("Stamina", "Regen", 10f, 0.1f, 100f, "Base grounded regeneration per second; increases at low stamina like vanilla mounts.");
			patches = new Harmony("torubaki.rideabledrakes");
			patches.PatchAll();
		}

		private ConfigEntry<float> Setting(string section, string key, float value, float min, float max, string description)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			return ((BaseUnityPlugin)this).Config.Bind<float>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()));
		}

		private void OnDestroy()
		{
			DrakeMount[] array = Object.FindObjectsByType<DrakeMount>((FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				array[i].DetachLocalRider();
			}
			Harmony obj = patches;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if (Object.op_Implicit((Object)(object)CreatureRegistration.Root))
			{
				Object.Destroy((Object)(object)CreatureRegistration.Root);
			}
		}
	}
}