Decompiled source of MountedArchery v1.0.0

MountedArchery.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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("MountedArchery")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ce2e7fb5fe0ca0d12f467aef05f7f857746877a8")]
[assembly: AssemblyProduct("MountedArchery")]
[assembly: AssemblyTitle("MountedArchery")]
[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 MountedArchery
{
	[HarmonyPatch]
	internal static class AimAtFirePatches
	{
		private static bool s_errorLogged;

		[HarmonyPatch(typeof(Attack), "GetProjectileSpawnPoint")]
		[HarmonyPrefix]
		private static void Align(Attack __instance)
		{
			//IL_001d: 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_0029: 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)
			try
			{
				Humanoid obj = Riding.Attacker.Invoke(__instance);
				Player val = (Player)(object)((obj is Player) ? obj : null);
				if (Riding.IsRiding(val))
				{
					Quaternion lookYaw = ((Character)val).GetLookYaw();
					((Component)val).transform.rotation = lookYaw;
					Rigidbody val2 = Riding.Body.Invoke((Character)(object)val);
					if ((Object)(object)val2 != (Object)null)
					{
						val2.rotation = lookYaw;
					}
					Riding.AimEye(val);
				}
			}
			catch (Exception arg)
			{
				if (!s_errorLogged)
				{
					s_errorLogged = true;
					Plugin.Log.LogError((object)$"Aiming a shot from the saddle failed (logged once): {arg}");
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class BowDrawPatches
	{
		internal static Player Drawing;

		private static bool s_errorLogged;

		[HarmonyPatch(typeof(Player), "UpdateAttackBowDraw")]
		[HarmonyPrefix]
		private static void Begin(Player __instance, ItemData weapon)
		{
			try
			{
				if (Riding.IsRiding(__instance) && Riding.IsBow(Riding.AttackOf(weapon, secondary: false)))
				{
					Drawing = __instance;
				}
			}
			catch (Exception e)
			{
				Drawing = null;
				LogOnce("Drawing a bow from the saddle failed (logged once)", e);
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateAttackBowDraw")]
		[HarmonyFinalizer]
		private static void End()
		{
			Drawing = null;
		}

		[HarmonyPatch(typeof(Player), "IsAttached")]
		[HarmonyPostfix]
		private static void IsAttached(Player __instance, ref bool __result)
		{
			if ((Object)(object)Drawing != (Object)null && (Object)(object)__instance == (Object)(object)Drawing)
			{
				__result = false;
			}
		}

		private static void LogOnce(string what, Exception e)
		{
			if (!s_errorLogged)
			{
				s_errorLogged = true;
				Plugin.Log.LogError((object)$"{what}: {e}");
			}
		}
	}
	[HarmonyPatch]
	internal static class FaceAimPatches
	{
		private static bool s_errorLogged;

		[HarmonyPatch(typeof(Player), "UpdateAttach")]
		[HarmonyPostfix]
		private static void FaceAim(Player __instance)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_006f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Riding.IsRiding(__instance))
				{
					return;
				}
				bool bowWeapon = Riding.IsBow(Riding.AttackOf(((Humanoid)__instance).GetCurrentWeapon(), secondary: false));
				float sinceShotStart = Time.time - StartAttackPatches.ShotStartedAt;
				if (SaddleRules.Shooting(((Character)__instance).InAttack(), sinceShotStart, Riding.DrawTime.Invoke((Humanoid)(object)__instance), bowWeapon))
				{
					Quaternion lookYaw = ((Character)__instance).GetLookYaw();
					((Component)__instance).transform.rotation = lookYaw;
					Rigidbody val = Riding.Body.Invoke((Character)(object)__instance);
					if ((Object)(object)val != (Object)null)
					{
						val.rotation = lookYaw;
					}
				}
			}
			catch (Exception e)
			{
				LogOnce("Turning the rider to the aim failed (logged once)", e);
			}
		}

		private static void LogOnce(string what, Exception e)
		{
			if (!s_errorLogged)
			{
				s_errorLogged = true;
				Plugin.Log.LogError((object)$"{what}: {e}");
			}
		}
	}
	[HarmonyPatch]
	internal static class HoverPatches
	{
		private static readonly RaycastHit[] s_hits = (RaycastHit[])(object)new RaycastHit[64];

		private static readonly IComparer<RaycastHit> s_byDistance = Comparer<RaycastHit>.Create((RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));

		private static bool s_errorLogged;

		[HarmonyPatch(typeof(Player), "UpdateHover")]
		[HarmonyPostfix]
		private static void LookAtCreature(Player __instance)
		{
			try
			{
				if (Riding.IsRiding(__instance) && !((Character)__instance).InPlaceMode())
				{
					IDoodadController doodadController = __instance.GetDoodadController();
					Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
					Character mount = (((Object)(object)val != (Object)null) ? val.GetCharacter() : null);
					Riding.HoverCreature.Invoke(__instance) = CreatureUnderCrosshair(__instance, mount);
				}
			}
			catch (Exception arg)
			{
				if (!s_errorLogged)
				{
					s_errorLogged = true;
					Plugin.Log.LogError((object)$"Showing enemies' health from the saddle failed (logged once): {arg}");
				}
			}
		}

		private static Character CreatureUnderCrosshair(Player player, Character mount)
		{
			//IL_0019: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			GameCamera instance = GameCamera.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			Transform transform = ((Component)instance).transform;
			int num = Physics.RaycastNonAlloc(transform.position, transform.forward, s_hits, 50f, Riding.InteractMask.Invoke(player));
			Array.Sort(s_hits, 0, num, s_byDistance);
			for (int i = 0; i < num; i++)
			{
				Collider collider = ((RaycastHit)(ref s_hits[i])).collider;
				Rigidbody attachedRigidbody = collider.attachedRigidbody;
				if (Object.op_Implicit((Object)(object)attachedRigidbody) && (Object)(object)((Component)attachedRigidbody).gameObject == (Object)(object)((Component)player).gameObject)
				{
					continue;
				}
				Character val = (Object.op_Implicit((Object)(object)attachedRigidbody) ? ((Component)attachedRigidbody).GetComponent<Character>() : ((Component)collider).GetComponent<Character>());
				if (!((Object)(object)val != (Object)null) || !((Object)(object)val == (Object)(object)mount))
				{
					if ((Object)(object)val == (Object)null)
					{
						return null;
					}
					BaseAI baseAI = val.GetBaseAI();
					if ((Object.op_Implicit((Object)(object)baseAI) && baseAI.IsSleeping()) || ParticleMist.IsMistBlocked(((Character)player).GetCenterPoint(), val.GetCenterPoint()))
					{
						return null;
					}
					return val;
				}
			}
			return null;
		}
	}
	[HarmonyPatch]
	internal static class KeepSaddlePatches
	{
		private static bool s_errorLogged;

		[HarmonyPatch(typeof(Player), "SetControls")]
		[HarmonyPrefix]
		private static void Hide(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold, out AttackFlags __state)
		{
			__state = default(AttackFlags);
			try
			{
				if (Riding.IsRiding(__instance))
				{
					ItemData currentWeapon = ((Humanoid)__instance).GetCurrentWeapon();
					AttackFlags input = new AttackFlags
					{
						Attack = attack,
						AttackHold = attackHold,
						Secondary = secondaryAttack,
						SecondaryHold = secondaryAttackHold
					};
					__state = SaddleRules.Hide(riding: true, input, Riding.KeepsSaddle(Riding.AttackOf(currentWeapon, secondary: false), secondary: false), Riding.KeepsSaddle(Riding.AttackOf(currentWeapon, secondary: true), secondary: true));
					if (__state.Any)
					{
						AttackFlags attackFlags = SaddleRules.Remaining(input, __state);
						attack = attackFlags.Attack;
						attackHold = attackFlags.AttackHold;
						secondaryAttack = attackFlags.Secondary;
						secondaryAttackHold = attackFlags.SecondaryHold;
					}
				}
			}
			catch (Exception e)
			{
				__state = default(AttackFlags);
				LogOnce("Keeping the saddle on a shot failed (logged once; vanilla dismounts)", e);
			}
		}

		[HarmonyPatch(typeof(Player), "SetControls")]
		[HarmonyPostfix]
		private static void Restore(Player __instance, AttackFlags __state)
		{
			try
			{
				if (__state.Any)
				{
					AttackFlags attackFlags = SaddleRules.Restore(Riding.IsRiding(__instance), __state);
					if (attackFlags.Attack)
					{
						Riding.AttackFlag.Invoke((Character)(object)__instance) = true;
					}
					if (attackFlags.AttackHold)
					{
						Riding.AttackHoldFlag.Invoke((Character)(object)__instance) = true;
					}
					if (attackFlags.Secondary)
					{
						Riding.SecondaryFlag.Invoke((Character)(object)__instance) = true;
					}
					if (attackFlags.SecondaryHold)
					{
						Riding.SecondaryHoldFlag.Invoke((Character)(object)__instance) = true;
					}
				}
			}
			catch (Exception e)
			{
				LogOnce("Passing a shot on to the attack update failed (logged once)", e);
			}
		}

		private static void LogOnce(string what, Exception e)
		{
			if (!s_errorLogged)
			{
				s_errorLogged = true;
				Plugin.Log.LogError((object)$"{what}: {e}");
			}
		}
	}
	[HarmonyPatch]
	internal static class LaunchPatches
	{
		private static Player s_rider;

		private static bool s_errorLogged;

		[HarmonyPatch(typeof(Attack), "FireProjectileBurst")]
		[HarmonyPrefix]
		private static void Begin(Attack __instance)
		{
			try
			{
				Humanoid obj = Riding.Attacker.Invoke(__instance);
				Player val = (Player)(object)((obj is Player) ? obj : null);
				s_rider = (Riding.IsRiding(val) ? val : null);
			}
			catch (Exception e)
			{
				s_rider = null;
				LogOnce(e);
			}
		}

		[HarmonyPatch(typeof(Attack), "FireProjectileBurst")]
		[HarmonyFinalizer]
		private static void End()
		{
			s_rider = null;
		}

		[HarmonyPatch(typeof(Projectile), "Setup")]
		[HarmonyPrefix]
		private static void Launch(Character owner, ref Vector3 velocity)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!((Object)(object)s_rider == (Object)null) && !((Object)(object)owner != (Object)(object)s_rider))
				{
					velocity = ShotRules.LaunchVelocity(velocity, ((Character)s_rider).GetVelocity());
				}
			}
			catch (Exception e)
			{
				LogOnce(e);
			}
		}

		private static void LogOnce(Exception e)
		{
			if (!s_errorLogged)
			{
				s_errorLogged = true;
				Plugin.Log.LogError((object)$"Adding the rider's speed to a shot failed (logged once): {e}");
			}
		}
	}
	[HarmonyPatch]
	internal static class PickupPatches
	{
		private static readonly Collider[] s_colliders = (Collider[])(object)new Collider[100];

		private static bool s_errorLogged;

		[HarmonyPatch(typeof(Player), "AutoPickup")]
		[HarmonyPostfix]
		private static void AroundTheMount(Player __instance, float dt)
		{
			//IL_005c: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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_00bf: 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_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: 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)
			try
			{
				if (!Riding.IsRiding(__instance) || ((Character)__instance).IsTeleporting() || !Riding.AutoPickupOn.Invoke())
				{
					return;
				}
				IDoodadController doodadController = __instance.GetDoodadController();
				Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
				Character val2 = (((Object)(object)val != (Object)null) ? val.GetCharacter() : null);
				if ((Object)(object)val2 == (Object)null)
				{
					return;
				}
				CapsuleCollider collider = val2.GetCollider();
				Vector3 val3 = ((Component)val2).transform.position + Vector3.up;
				float num = PickupRules.Reach(__instance.m_autoPickupRange, ((Object)(object)collider != (Object)null) ? collider.radius : 0f);
				Vector3 val4 = ((Component)__instance).transform.position + Vector3.up;
				Vector3 val5 = ((Vector3.Distance(val4, val3) <= num) ? val4 : val3);
				Vector3 velocity = ((Character)__instance).GetVelocity();
				Inventory inventory = ((Humanoid)__instance).GetInventory();
				int num2 = Physics.OverlapSphereNonAlloc(val3, num, s_colliders, Riding.AutoPickupMask.Invoke(__instance));
				for (int i = 0; i < num2; i++)
				{
					Rigidbody attachedRigidbody = s_colliders[i].attachedRigidbody;
					if (!Object.op_Implicit((Object)(object)attachedRigidbody))
					{
						continue;
					}
					ItemDrop component = ((Component)attachedRigidbody).GetComponent<ItemDrop>();
					FloatingTerrainDummy val6 = null;
					if ((Object)(object)component == (Object)null && Object.op_Implicit((Object)(object)(val6 = ((Component)attachedRigidbody).GetComponent<FloatingTerrainDummy>())) && (Object)(object)val6.m_parent != (Object)null)
					{
						component = ((Component)val6.m_parent).GetComponent<ItemDrop>();
					}
					if ((Object)(object)component == (Object)null || !component.m_autoPickup || component.IsPiece() || ((Humanoid)__instance).HaveUniqueKey(component.m_itemData.m_shared.m_name))
					{
						continue;
					}
					ZNetView component2 = ((Component)component).GetComponent<ZNetView>();
					if ((Object)(object)component2 == (Object)null || !component2.IsValid())
					{
						continue;
					}
					if (!component.CanPickup(true))
					{
						component.RequestOwn();
					}
					else
					{
						if (component.InTar())
						{
							continue;
						}
						component.Load();
						if (!inventory.CanAddItem(component.m_itemData, -1) || component.m_itemData.GetWeight(-1) + inventory.GetTotalWeight() > __instance.GetMaxCarryWeight() || Vector3.Distance(((Component)component).transform.position, val3) > num)
						{
							continue;
						}
						Vector3 toTarget = val5 - ((Component)component).transform.position;
						if (((Vector3)(ref toTarget)).magnitude < 0.3f)
						{
							((Humanoid)__instance).Pickup(((Component)component).gameObject, true, true);
							continue;
						}
						Vector3 val7 = PickupRules.Step(toTarget, velocity, dt);
						Transform transform = ((Component)component).transform;
						transform.position += val7;
						if (Object.op_Implicit((Object)(object)val6))
						{
							Transform transform2 = ((Component)val6).transform;
							transform2.position += val7;
						}
					}
				}
			}
			catch (Exception arg)
			{
				if (!s_errorLogged)
				{
					s_errorLogged = true;
					Plugin.Log.LogError((object)$"Picking items up from the saddle failed (logged once): {arg}");
				}
			}
		}
	}
	internal static class PickupRules
	{
		public const float PullSpeed = 15f;

		public const float PickupDistance = 0.3f;

		public static float Reach(float gameRange, float bodyRadius)
		{
			return gameRange + Mathf.Max(0f, bodyRadius);
		}

		public static Vector3 Step(Vector3 toTarget, Vector3 riderVelocity, float dt)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			return ((Vector3)(ref toTarget)).normalized * (15f * dt) + riderVelocity * dt;
		}
	}
	[BepInPlugin("algo7.mountedarchery", "MountedArchery", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "algo7.mountedarchery";

		public const string Name = "MountedArchery";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			if (Application.isBatchMode)
			{
				Log.LogInfo((object)"MountedArchery loaded (v1.0.0): dedicated server, nothing to do");
				return;
			}
			Install(new Harmony("algo7.mountedarchery"));
			Log.LogInfo((object)"MountedArchery loaded (v1.0.0)");
		}

		private static void Install(Harmony harmony)
		{
			if (!Riding.Prepare())
			{
				return;
			}
			if (!TryPatch(harmony, typeof(KeepSaddlePatches), "saddle hook") || !TryPatch(harmony, typeof(StartAttackPatches), "attack start hook") || !TryPatch(harmony, typeof(AimAtFirePatches), "fire aim hook") || !TryPatch(harmony, typeof(RidePosePatches), "seat pose hook"))
			{
				harmony.UnpatchSelf();
				Log.LogError((object)"Mounted shooting is off: attacks dismount you as in the unmodded game");
				return;
			}
			if (!TryPatch(harmony, typeof(BowDrawPatches), "bow draw hook"))
			{
				Riding.BowsEnabled = false;
				Log.LogWarning((object)"Bows dismount you as in the unmodded game (crossbows, spears and staffs still fire from the saddle)");
			}
			if (!TryPatch(harmony, typeof(FaceAimPatches), "turn hook"))
			{
				Log.LogWarning((object)"The rider won't visibly turn to the aim (shots still fly true)");
			}
			if (!TryPatch(harmony, typeof(SeatedCameraPatches), "seated camera hook"))
			{
				Log.LogWarning((object)"Shots from the saddle start a little higher against the crosshair than on foot");
			}
			if (Riding.HoverCreature != null && !TryPatch(harmony, typeof(HoverPatches), "health bar hook"))
			{
				Log.LogWarning((object)"Enemies' health bars won't show while riding (as in the unmodded game)");
			}
			if (Riding.AutoPickupOn != null && !TryPatch(harmony, typeof(PickupPatches), "pickup hook"))
			{
				Log.LogWarning((object)"Items won't be picked up from the saddle (as in the unmodded game)");
			}
			if (!TryPatch(harmony, typeof(LaunchPatches), "launch speed hook"))
			{
				Log.LogWarning((object)"Shots from a moving animal leave at the weapon's own speed (as in the unmodded game)");
			}
		}

		internal static bool TryPatch(Harmony harmony, Type patches, string what)
		{
			try
			{
				harmony.PatchAll(patches);
				return true;
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Could not install the {what}: {arg}");
				return false;
			}
		}
	}
	[HarmonyPatch]
	internal static class RidePosePatches
	{
		private static Player s_shot;

		private static bool s_fired;

		private static bool s_keepsFiring;

		private static bool s_poseOff;

		private static bool s_errorLogged;

		[HarmonyPatch(typeof(Humanoid), "StartAttack")]
		[HarmonyPostfix]
		private static void Started(Humanoid __instance, bool secondaryAttack, bool __result)
		{
			try
			{
				Player seated = StartAttackPatches.Seated;
				if (__result && !((Object)(object)seated == (Object)null) && !((Object)(object)__instance != (Object)(object)seated))
				{
					Attack val = Riding.AttackOf(((Humanoid)seated).GetCurrentWeapon(), secondaryAttack);
					if ((Object)(object)s_shot != (Object)(object)seated)
					{
						s_poseOff = false;
					}
					s_shot = seated;
					s_fired = false;
					s_keepsFiring = val != null && (val.m_loopingAttack || val.m_projectileBursts > 1);
				}
			}
			catch (Exception e)
			{
				LogOnce("Keeping the attack clip for a shot from the saddle failed (logged once)", e);
			}
		}

		[HarmonyPatch(typeof(Humanoid), "OnAttackTrigger")]
		[HarmonyPostfix]
		private static void Fired(Humanoid __instance)
		{
			if ((Object)(object)s_shot != (Object)null && (Object)(object)__instance == (Object)(object)s_shot)
			{
				s_fired = true;
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateAttach")]
		[HarmonyPostfix]
		private static void Step(Player __instance)
		{
			try
			{
				if (!Riding.IsRiding(__instance))
				{
					if ((Object)(object)__instance == (Object)(object)s_shot)
					{
						Forget();
					}
					return;
				}
				bool flag = ((Character)__instance).InAttack();
				ZSyncAnimation val = Riding.Anim.Invoke((Character)(object)__instance);
				if (!flag && !((Character)__instance).InMinorAction() && !((Character)__instance).InEmote() && (Object)(object)val != (Object)null)
				{
					val.SetSpeed(1f);
				}
				if ((Object)(object)__instance != (Object)(object)s_shot)
				{
					return;
				}
				bool flag2 = SaddleRules.PoseBack(s_fired, s_keepsFiring, flag, Time.time - StartAttackPatches.ShotStartedAt);
				if (flag2)
				{
					if (s_poseOff)
					{
						SetPose(__instance, on: true);
					}
					Forget();
				}
				else if (!s_poseOff && SaddleRules.PoseOff(Riding.NextOrCurrentAnimHash((Character)(object)__instance) == Riding.AttackTag, flag2))
				{
					s_poseOff = SetPose(__instance, on: false);
				}
			}
			catch (Exception e)
			{
				if ((Object)(object)__instance == (Object)(object)s_shot)
				{
					try
					{
						if (s_poseOff && Riding.IsRiding(__instance))
						{
							SetPose(__instance, on: true);
						}
					}
					catch (Exception)
					{
					}
					Forget();
				}
				LogOnce("Putting the rider back in the seat's pose failed (logged once)", e);
			}
		}

		private static void Forget()
		{
			s_shot = null;
			s_poseOff = false;
		}

		private static bool SetPose(Player player, bool on)
		{
			string text = Riding.AttachAnimation.Invoke(player);
			ZSyncAnimation val = Riding.Anim.Invoke((Character)(object)player);
			if (string.IsNullOrEmpty(text) || (Object)(object)val == (Object)null)
			{
				return false;
			}
			val.SetBool(text, on);
			return true;
		}

		private static void LogOnce(string what, Exception e)
		{
			if (!s_errorLogged)
			{
				s_errorLogged = true;
				Plugin.Log.LogError((object)$"{what}: {e}");
			}
		}
	}
	internal static class Riding
	{
		internal static FieldRef<Player, bool> Attached;

		internal static FieldRef<Character, bool> AttackFlag;

		internal static FieldRef<Character, bool> AttackHoldFlag;

		internal static FieldRef<Character, bool> SecondaryFlag;

		internal static FieldRef<Character, bool> SecondaryHoldFlag;

		internal static FieldRef<Humanoid, float> DrawTime;

		internal static FieldRef<Character, Rigidbody> Body;

		internal static Func<Character, int> NextOrCurrentAnimHash;

		internal static int SittingTag;

		internal static int AttackTag;

		internal static FieldRef<Attack, Humanoid> Attacker;

		internal static Action<Player> AimEye;

		internal static FieldRef<Player, string> AttachAnimation;

		internal static FieldRef<Character, ZSyncAnimation> Anim;

		internal static FieldRef<GameCamera, Vector3> CameraBaseOffset;

		internal static FieldRef<Player, Character> HoverCreature;

		internal static FieldRef<Player, int> InteractMask;

		internal static FieldRef<bool> AutoPickupOn;

		internal static FieldRef<Player, int> AutoPickupMask;

		internal static bool BowsEnabled = true;

		internal static bool Prepare()
		{
			if (Attached != null)
			{
				return true;
			}
			try
			{
				Attached = AccessTools.FieldRefAccess<Player, bool>("m_attached");
				AttackFlag = AccessTools.FieldRefAccess<Character, bool>("m_attack");
				AttackHoldFlag = AccessTools.FieldRefAccess<Character, bool>("m_attackHold");
				SecondaryFlag = AccessTools.FieldRefAccess<Character, bool>("m_secondaryAttack");
				SecondaryHoldFlag = AccessTools.FieldRefAccess<Character, bool>("m_secondaryAttackHold");
				DrawTime = AccessTools.FieldRefAccess<Humanoid, float>("m_attackDrawTime");
				Body = AccessTools.FieldRefAccess<Character, Rigidbody>("m_body");
				MethodInfo methodInfo = AccessTools.Method(typeof(Character), "GetNextOrCurrentAnimHash", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					throw new MissingMethodException("Character.GetNextOrCurrentAnimHash");
				}
				NextOrCurrentAnimHash = AccessTools.MethodDelegate<Func<Character, int>>(methodInfo, (object)null, true);
				SittingTag = AccessTools.StaticFieldRefAccess<int>(typeof(Character), "s_animatorTagSitting");
				AttackTag = AccessTools.StaticFieldRefAccess<int>(typeof(Humanoid), "s_animatorTagAttack");
				Attacker = AccessTools.FieldRefAccess<Attack, Humanoid>("m_character");
				MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(Player), "UpdateEyeRotation", (Type[])null, (Type[])null);
				if (methodInfo2 == null)
				{
					throw new MissingMethodException("Player.UpdateEyeRotation");
				}
				AimEye = AccessTools.MethodDelegate<Action<Player>>(methodInfo2, (object)null, false);
				AttachAnimation = AccessTools.FieldRefAccess<Player, string>("m_attachAnimation");
				Anim = AccessTools.FieldRefAccess<Character, ZSyncAnimation>("m_zanim");
			}
			catch (Exception ex)
			{
				Attached = null;
				Plugin.Log.LogError((object)("Mounted shooting is off: a game member the hooks need wasn't found (a game update?): " + ex.Message));
				return false;
			}
			try
			{
				CameraBaseOffset = AccessTools.FieldRefAccess<GameCamera, Vector3>("m_currentBaseOffset");
			}
			catch (Exception ex2)
			{
				CameraBaseOffset = null;
				Plugin.Log.LogWarning((object)("Shots from the saddle line up with where the camera settles, not where it is (a game update?): " + ex2.Message));
			}
			try
			{
				HoverCreature = AccessTools.FieldRefAccess<Player, Character>("m_hoveringCreature");
				InteractMask = AccessTools.FieldRefAccess<Player, int>("m_interactMask");
			}
			catch (Exception ex3)
			{
				HoverCreature = null;
				InteractMask = null;
				Plugin.Log.LogWarning((object)("Enemies' health bars won't show while riding (a game update?): " + ex3.Message));
			}
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(Player), "m_enableAutoPickup");
				if (fieldInfo == null || !fieldInfo.IsStatic)
				{
					throw new MissingFieldException("Player.m_enableAutoPickup");
				}
				AutoPickupOn = AccessTools.StaticFieldRefAccess<bool>(fieldInfo);
				AutoPickupMask = AccessTools.FieldRefAccess<Player, int>("m_autoPickupMask");
			}
			catch (Exception ex4)
			{
				AutoPickupOn = null;
				AutoPickupMask = null;
				Plugin.Log.LogWarning((object)("Items won't be picked up from the saddle (a game update?): " + ex4.Message));
			}
			return true;
		}

		internal static bool IsRiding(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer || Attached == null || !Attached.Invoke(player))
			{
				return false;
			}
			return ((Character)player).IsRiding();
		}

		internal static Attack AttackOf(ItemData weapon, bool secondary)
		{
			SharedData val = weapon?.m_shared;
			if (val == null)
			{
				return null;
			}
			if (!secondary)
			{
				return val.m_attack;
			}
			return val.m_secondaryAttack;
		}

		internal static bool IsProjectile(Attack attack)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			if (attack != null)
			{
				return SaddleRules.IsProjectile(attack.m_attackType, attack.m_bowDraw, BowsEnabled, !string.IsNullOrEmpty(attack.m_attackAnimation));
			}
			return false;
		}

		internal static bool KeepsSaddle(Attack attack, bool secondary)
		{
			if (attack != null)
			{
				return SaddleRules.KeepsSaddle(IsProjectile(attack), !string.IsNullOrEmpty(attack.m_attackAnimation), secondary);
			}
			return false;
		}

		internal static bool IsBow(Attack attack)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (attack != null && (int)attack.m_attackType == 2)
			{
				return attack.m_bowDraw;
			}
			return false;
		}
	}
	internal struct AttackFlags
	{
		public bool Attack;

		public bool AttackHold;

		public bool Secondary;

		public bool SecondaryHold;

		public bool Any
		{
			get
			{
				if (!Attack && !AttackHold && !Secondary)
				{
					return SecondaryHold;
				}
				return true;
			}
		}
	}
	internal static class SaddleRules
	{
		public const float ShotStartGrace = 0.3f;

		public static bool IsProjectile(AttackType type, bool bowDraw, bool bowsEnabled, bool hasAnimation)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Invalid comparison between Unknown and I4
			if (!hasAnimation || (int)type != 2)
			{
				return false;
			}
			return !bowDraw || bowsEnabled;
		}

		public static bool KeepsSaddle(bool isProjectile, bool hasAnimation, bool secondary)
		{
			if (!isProjectile)
			{
				if (secondary)
				{
					return !hasAnimation;
				}
				return false;
			}
			return true;
		}

		public static AttackFlags Hide(bool riding, AttackFlags input, bool primaryKeepsSaddle, bool secondaryKeepsSaddle)
		{
			AttackFlags result = default(AttackFlags);
			if (!riding)
			{
				return result;
			}
			if (primaryKeepsSaddle)
			{
				result.Attack = input.Attack;
				result.AttackHold = input.AttackHold;
			}
			if (secondaryKeepsSaddle)
			{
				result.Secondary = input.Secondary;
				result.SecondaryHold = input.SecondaryHold;
			}
			return result;
		}

		public static AttackFlags Remaining(AttackFlags input, AttackFlags hidden)
		{
			return new AttackFlags
			{
				Attack = (input.Attack && !hidden.Attack),
				AttackHold = (input.AttackHold && !hidden.AttackHold),
				Secondary = (input.Secondary && !hidden.Secondary),
				SecondaryHold = (input.SecondaryHold && !hidden.SecondaryHold)
			};
		}

		public static AttackFlags Restore(bool stillAttached, AttackFlags hidden)
		{
			if (!stillAttached)
			{
				return default(AttackFlags);
			}
			return hidden;
		}

		public static bool AttackPlaying(bool inAttack, float sinceShotStart)
		{
			if (!inAttack)
			{
				return sinceShotStart < 0.3f;
			}
			return true;
		}

		public static bool PoseOff(bool fullBodyInAttack, bool poseBack)
		{
			if (fullBodyInAttack)
			{
				return !poseBack;
			}
			return false;
		}

		public static bool PoseBack(bool shotFired, bool keepsFiring, bool inAttack, float sinceShotStart)
		{
			if (!shotFired || keepsFiring)
			{
				return !AttackPlaying(inAttack, sinceShotStart);
			}
			return true;
		}

		public static bool Shooting(bool inAttack, float sinceShotStart, float drawTime, bool bowWeapon)
		{
			if (!AttackPlaying(inAttack, sinceShotStart))
			{
				if (bowWeapon)
				{
					return drawTime > 0f;
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class SeatedCameraPatches
	{
		private static bool s_errorLogged;

		[HarmonyPatch(typeof(Attack), "GetProjectileSpawnPoint")]
		[HarmonyPostfix]
		private static void Shift(Attack __instance, ref Vector3 spawnPoint)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Humanoid obj = Riding.Attacker.Invoke(__instance);
				Player val = (Player)(object)((obj is Player) ? obj : null);
				if (Riding.IsRiding(val) && string.IsNullOrEmpty(__instance.m_attackOriginJoint))
				{
					spawnPoint += ShotRules.ShotShift(CameraBase(val), ((Character)val).m_eye.position);
				}
			}
			catch (Exception arg)
			{
				if (!s_errorLogged)
				{
					s_errorLogged = true;
					Plugin.Log.LogError((object)$"Starting a shot at the seated camera's height failed (logged once): {arg}");
				}
			}
		}

		internal static Vector3 CameraBase(Player player)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			GameCamera instance = GameCamera.instance;
			if (Riding.CameraBaseOffset != null && (Object)(object)instance != (Object)null)
			{
				return ((Component)player).transform.position + Riding.CameraBaseOffset.Invoke(instance);
			}
			return ShotRules.SeatedCameraBase(((Character)player).GetHeadPoint());
		}
	}
	internal static class ShotRules
	{
		public const float SeatedCameraAboveHead = 0.3f;

		public const float MinLaunchSpeed = 1f;

		public static Vector3 ShotShift(Vector3 cameraBase, Vector3 eye)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return cameraBase - eye;
		}

		public static Vector3 SeatedCameraBase(Vector3 head)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: 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_0010: Unknown result type (might be due to invalid IL or missing references)
			return head + Vector3.up * 0.3f;
		}

		public static Vector3 LaunchVelocity(Vector3 velocity, Vector3 riderVelocity)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0028: 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_0010: Unknown result type (might be due to invalid IL or missing references)
			float magnitude = ((Vector3)(ref velocity)).magnitude;
			if (magnitude < 0.01f)
			{
				return velocity;
			}
			Vector3 val = velocity / magnitude;
			return val * Mathf.Max(Mathf.Min(magnitude, 1f), magnitude + Vector3.Dot(riderVelocity, val));
		}
	}
	[HarmonyPatch]
	internal static class StartAttackPatches
	{
		internal static Player Seated;

		internal static float ShotStartedAt = float.NegativeInfinity;

		private static bool s_errorLogged;

		[HarmonyPatch(typeof(Humanoid), "StartAttack")]
		[HarmonyPrefix]
		private static void Begin(Humanoid __instance, bool secondaryAttack)
		{
			try
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (Riding.IsRiding(val) && Riding.IsProjectile(Riding.AttackOf(((Humanoid)val).GetCurrentWeapon(), secondaryAttack)))
				{
					Seated = val;
				}
			}
			catch (Exception e)
			{
				Seated = null;
				LogOnce("Starting a shot from the saddle failed (logged once)", e);
			}
		}

		[HarmonyPatch(typeof(Humanoid), "StartAttack")]
		[HarmonyPostfix]
		private static void Started(Humanoid __instance, bool __result)
		{
			if (__result && (Object)(object)Seated != (Object)null && (Object)(object)__instance == (Object)(object)Seated)
			{
				ShotStartedAt = Time.time;
			}
		}

		[HarmonyPatch(typeof(Humanoid), "StartAttack")]
		[HarmonyFinalizer]
		private static void End()
		{
			Seated = null;
		}

		[HarmonyPatch(typeof(Character), "CanMove")]
		[HarmonyPostfix]
		private static void CanMove(Character __instance, ref bool __result)
		{
			try
			{
				if (!__result && !((Object)(object)Seated == (Object)null) && !((Object)(object)__instance != (Object)(object)Seated))
				{
					__result = !__instance.IsStaggering() && Riding.NextOrCurrentAnimHash(__instance) == Riding.SittingTag;
				}
			}
			catch (Exception e)
			{
				LogOnce("Allowing a shot from the saddle failed (logged once)", e);
			}
		}

		private static void LogOnce(string what, Exception e)
		{
			if (!s_errorLogged)
			{
				s_errorLogged = true;
				Plugin.Log.LogError((object)$"{what}: {e}");
			}
		}
	}
	internal static class PluginInfo
	{
		public const string Version = "1.0.0";
	}
}