Decompiled source of Aicho Enhanced Movement v1.0.2

AichoEnhancedMovement.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Audio;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AichoEnhancedMovement")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AichoEnhancedMovement")]
[assembly: AssemblyTitle("AichoEnhancedMovement")]
[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 AichoEnhancedMovement
{
	[BepInPlugin("aicho.sprintequip", "Aicho Enhanced Movement", "1.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginVersion = "1.1.0";

		internal static ManualLogSource Log;

		public const float VanillaStaminaRegen = 5f;

		public static ConfigEntry<bool> EnhancedAutoRun;

		public static ConfigEntry<bool> AutoRunStopWithKey;

		public static ConfigEntry<bool> AutoRunResumeSprint;

		public static ConfigEntry<bool> PauseSprintToReload;

		public static ConfigEntry<bool> StopOnAttack;

		public static ConfigEntry<bool> ShowAutoRunIcon;

		public static ConfigEntry<bool> AutoRunFollowRoads;

		public static ConfigEntry<KeyCode> FollowRoadsModifier;

		public static ConfigEntry<bool> FreeLookEnabled;

		public static ConfigEntry<KeyCode> FreeLookKey;

		public static ConfigEntry<float> FreeLookReturnTime;

		public static ConfigEntry<bool> StaminaBurstEnabled;

		public static ConfigEntry<float> StaminaBaseRegen;

		public static ConfigEntry<float> StaminaTimeMultiplier;

		public static ConfigEntry<float> StaminaBelowHalfMultiplier;

		public static ConfigEntry<float> StaminaAboveHalfMultiplier;

		public static ConfigEntry<float> StaminaRestedBurstThreshold;

		public static ConfigEntry<float> StaminaBurstFadeRange;

		public static ConfigEntry<bool> StaminaBurstBarColorEnabled;

		public static ConfigEntry<Color> StaminaBurstBarColor;

		public static ConfigEntry<float> RoadRunStaminaMultiplier;

		public static ConfigEntry<float> HoePathRunSpeedMultiplier;

		public static ConfigEntry<float> RestedHoePathRunSpeedMultiplier;

		public static ConfigEntry<bool> MountHoePathSpeed;

		public static ConfigEntry<bool> ShowOnPathIcon;

		public static ConfigEntry<bool> MountStabilizeCamera;

		public static ConfigEntry<bool> CallMountEnabled;

		public static ConfigEntry<KeyCode> CallMountKey;

		public static ConfigEntry<float> CallMountRadius;

		public static ConfigEntry<float> CallMountArriveDistance;

		public static ConfigEntry<float> CallMountSoundVolume;

		public static ConfigEntry<bool> MountRespondsToCall;

		public static ConfigEntry<bool> EquipWhileSprinting;

		public static ConfigEntry<float> WeaponEquipTimeMultiplier;

		public static ConfigEntry<bool> ReloadOnlyWithAmmo;

		private void Awake()
		{
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			EnhancedAutoRun = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Auto Run", "EnhancedAutoRun", true, "Auto run mejorado: no se corta al moverte de lado con A/D, saltar, esquivar, agacharte ni usar herramientas, sigue a la cámara y solo se detiene con S (o con su tecla, ver StopWithAutoRunKey). Si es false, el auto run funciona como en vanilla y se desactivan también las demás funciones de auto run de este mod (seguir caminos, retomar el sprint, etc.).");
			AutoRunStopWithKey = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Auto Run", "StopWithAutoRunKey", true, "Volver a presionar la misma combinación (tecla de auto run, o modificador + tecla para el de caminos) detiene el auto run, además de S. La otra combinación cambia de modo sin detenerte.");
			AutoRunResumeSprint = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Auto Run", "ResumeSprintAfterExhaustion", true, "Si te quedas sin stamina corriendo con el auto run, vuelves a correr automáticamente al terminar el impulso de recarga (o al 100% si StaminaBurstEnabled es false).");
			PauseSprintToReload = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Auto Run", "PauseSprintToReload", true, "Al recargar la ballesta mientras corres, el sprint se pausa (sigues al trote) para que la recarga no se cancele, y se retoma solo al terminar.");
			StopOnAttack = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Auto Run", "StopOnAttack", true, "Empezar cualquier ataque (con cualquier arma o herramienta, incluido tensar el arco o la ballesta) detiene el auto run. Colocar piezas en modo construcción y bloquear no lo detienen.");
			ShowAutoRunIcon = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Auto Run", "ShowAutoRunIcon", true, "Muestra un ícono junto al minimapa mientras el auto run está activo (cambia sobre senderos y al seguir caminos).");
			AutoRunFollowRoads = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Seguir caminos", "FollowRoads", true, "Auto run que sigue solo las curvas de los senderos hechos con la azada, a pie y montado. Se activa con FollowRoadsModifier + la tecla de auto run del juego. Mover el mouse a los lados o presionar A/D lo pausa 1 segundo. Requiere EnhancedAutoRun.");
			FollowRoadsModifier = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("2 - Seguir caminos", "FollowRoadsModifier", (KeyCode)304, "Mantén esta tecla y presiona la tecla de auto run del juego para activar el auto run siguiendo el camino. La tecla de auto run sola activa el auto run normal.");
			FreeLookEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Camara libre", "FreeLookEnabled", true, "Permite mover la cámara libremente manteniendo FreeLookKey, a pie (con o sin auto run) y montado.");
			FreeLookKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("3 - Camara libre", "FreeLookKey", (KeyCode)308, "Mantén esta tecla para mover la cámara libremente: el personaje sigue moviéndose hacia la dirección que tenía al presionarla. Al soltarla, la cámara vuelve al frente.");
			FreeLookReturnTime = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Camara libre", "FreeLookReturnTime", 0f, "Segundos que tarda la cámara en volver al frente al soltar FreeLookKey. (0 = de inmediato)");
			StaminaBurstEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Stamina", "StaminaBurstEnabled", true, "Impulso de recarga: la stamina se recarga mucho más rápido hasta la mitad de la barra y después baja suavemente a la velocidad vanilla. Si es false, la recarga es la del juego normal.");
			StaminaBaseRegen = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Stamina", "BaseRegen", 8f, "Regeneración base de stamina durante el impulso (vanilla 5). Se multiplica además por BelowHalfMultiplier.");
			StaminaTimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Stamina", "TimeMultiplier", 1f, "Durante el impulso, multiplicador para Player.m_staminaRegenTimeMultiplier: la regeneración extra que se gana cuanto menos stamina te queda (vanilla 1).");
			StaminaBelowHalfMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Stamina", "BelowHalfMultiplier", 3f, "Fuerza del impulso: multiplicador cuando la stamina actual es <50% del máximo (o <RestedBurstThreshold descansado). (3.0 = 3x)");
			StaminaAboveHalfMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Stamina", "AboveHalfMultiplier", 1f, "Multiplicador de la recarga después del impulso (stamina >=50% del máximo). (1.0 = igual que vanilla)");
			StaminaRestedBurstThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Stamina", "RestedBurstThreshold", 0.6f, "Con el efecto Descansado, el impulso dura hasta este % de stamina en vez del 50% (Descansado alarga el impulso, no lo hace más fuerte). (0.6 = 60%)");
			StaminaBurstFadeRange = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Stamina", "BurstFadeRange", 0.15f, "Tramo (en % de stamina) después del final del impulso en el que la recarga baja gradualmente a la velocidad vanilla, para que el cambio no sea brusco. (0.15 = del 50% al 65%; 0 = cambio inmediato)");
			StaminaBurstBarColorEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Stamina", "BurstBarColorEnabled", true, "La barra de stamina cambia a BurstBarColor durante el impulso y vuelve al amarillo a medida que el impulso se apaga.");
			StaminaBurstBarColor = ((BaseUnityPlugin)this).Config.Bind<Color>("4 - Stamina", "BurstBarColor", new Color(0.45f, 0.9f, 0.3f, 1f), "Color de la barra de stamina durante el impulso de recarga.");
			RoadRunStaminaMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Senderos", "RoadRunStaminaMultiplier", 0.5f, "Multiplicador del gasto de stamina al correr sobre senderos hechos con la azada (tierra o pavimentados) o sobre construcciones. (0.5 = gasta la mitad, 1 = normal)");
			HoePathRunSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Senderos", "HoePathRunSpeedMultiplier", 1.1f, "Multiplicador de la velocidad al correr sobre senderos hechos con la azada. No aplica a construcciones. (1.1 = 10% más rápido, 1 = normal)");
			RestedHoePathRunSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Senderos", "RestedHoePathRunSpeedMultiplier", 1.15f, "Igual que HoePathRunSpeedMultiplier, pero con el efecto Descansado activo. (1.15 = 15% más rápido)");
			MountHoePathSpeed = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Senderos", "MountHoePathSpeed", true, "La montura que estés montando también recibe el bonus de velocidad en senderos (los mismos porcentajes que tu personaje).");
			ShowOnPathIcon = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Senderos", "ShowOnPathIcon", true, "Muestra el ícono \"En sendero\" junto al minimapa mientras pisas un sendero hecho con la azada, con o sin auto run.");
			MountStabilizeCamera = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - Montura", "StabilizeCamera", true, "Al ir montado, la cámara no se inclina con la montura y su altura se suaviza, para que los desniveles no la sacudan.");
			CallMountEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - Montura", "CallMountEnabled", true, "Permite llamar a la montura con CallMountKey.");
			CallMountKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("6 - Montura", "CallMountKey", (KeyCode)121, "Tecla para llamar a la montura domesticada (con silla) más cercana: silbas y la montura viene hacia ti esquivando obstáculos (te sigue buscando si te mueves) y al llegar se queda quieta a tu lado.");
			CallMountRadius = ((BaseUnityPlugin)this).Config.Bind<float>("6 - Montura", "CallMountRadius", 90f, "Distancia máxima (en metros) para encontrar una montura al llamarla.");
			CallMountArriveDistance = ((BaseUnityPlugin)this).Config.Bind<float>("6 - Montura", "CallMountArriveDistance", 5f, "Distancia (en metros, desde el centro de la montura) a la que se considera que la montura llegó y se queda quieta. Súbela si las monturas grandes te empujan al llegar. (Mínimo útil: 3, porque el juego detiene a quien te sigue a 3 m)");
			CallMountSoundVolume = ((BaseUnityPlugin)this).Config.Bind<float>("6 - Montura", "CallMountSoundVolume", 0.25f, "Volumen del silbido al llamar a la montura (0 = sin sonido, 1 = máximo). También respeta el volumen de efectos del juego.");
			MountRespondsToCall = ((BaseUnityPlugin)this).Config.Bind<bool>("6 - Montura", "MountRespondsToCall", true, "La montura responde al silbido con su propio sonido, que se oye desde donde está (más bajo cuanto más lejos).");
			EquipWhileSprinting = ((BaseUnityPlugin)this).Config.Bind<bool>("7 - Equipo", "EquipWhileSprinting", true, "Permite equipar y guardar armas o herramientas mientras corres, sin que el sprint cancele la animación.");
			WeaponEquipTimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("7 - Equipo", "WeaponEquipTimeMultiplier", 0.5f, "Multiplicador del tiempo de equipar/guardar armas, escudos, herramientas y antorchas (la armadura no cambia). (0.5 = 50% más rápido, 1 = normal)");
			ReloadOnlyWithAmmo = ((BaseUnityPlugin)this).Config.Bind<bool>("7 - Equipo", "ReloadOnlyWithAmmo", true, "La ballesta (y cualquier arma que se recargue) solo empieza a recargarse si tienes munición de su tipo en el inventario. En vanilla se recarga aunque no tengas virotes.");
			Log = ((BaseUnityPlugin)this).Logger;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Aicho Enhanced Movement 1.1.0 cargado");
			new Harmony("aicho.sprintequip").PatchAll();
		}

		public static string T(string spanish, string english)
		{
			if (Localization.instance == null || !(Localization.instance.GetSelectedLanguage() == "Spanish"))
			{
				return english;
			}
			return spanish;
		}

		public static bool IsRested(Player player)
		{
			if (((Character)player).GetSEMan() != null)
			{
				return ((Character)player).GetSEMan().HaveStatusEffect(SEMan.s_statusEffectRested);
			}
			return false;
		}

		public static float GetAfterBurst(Player player)
		{
			float maxStamina = ((Character)player).GetMaxStamina();
			float num = ((maxStamina > 0f) ? (player.GetStamina() / maxStamina) : 0f);
			float burstThreshold = GetBurstThreshold(player);
			float num2 = Mathf.Clamp(StaminaBurstFadeRange.Value, 0f, 1f - burstThreshold);
			float num3 = burstThreshold + num2;
			if (!(num <= burstThreshold))
			{
				if (!(num >= num3))
				{
					return Mathf.SmoothStep(0f, 1f, (num - burstThreshold) / num2);
				}
				return 1f;
			}
			return 0f;
		}

		public static float GetBurstThreshold(Player player)
		{
			if (!IsRested(player))
			{
				return 0.5f;
			}
			return Mathf.Clamp01(StaminaRestedBurstThreshold.Value);
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })]
	public static class PlayerUpdateStatsStaminaPatch
	{
		public struct SavedStamina
		{
			public float Regen;

			public float TimeMultiplier;
		}

		private static void Prefix(Player __instance, out SavedStamina __state)
		{
			__state = new SavedStamina
			{
				Regen = __instance.m_staminaRegen,
				TimeMultiplier = __instance.m_staminaRegenTimeMultiplier
			};
			if (Plugin.StaminaBurstEnabled.Value)
			{
				float afterBurst = Plugin.GetAfterBurst(__instance);
				float num = Mathf.Max(0f, Plugin.StaminaBaseRegen.Value) / 5f * Mathf.Max(0f, Plugin.StaminaBelowHalfMultiplier.Value);
				float num2 = Mathf.Max(0f, Plugin.StaminaAboveHalfMultiplier.Value);
				float num3 = ((afterBurst < 1f) ? GetRestedCompensation(__instance) : 1f);
				__instance.m_staminaRegen = __state.Regen * Mathf.Lerp(num * num3, num2, afterBurst);
				__instance.m_staminaRegenTimeMultiplier = __state.TimeMultiplier * Mathf.Lerp(Plugin.StaminaTimeMultiplier.Value, 1f, afterBurst);
			}
		}

		private static float GetRestedCompensation(Player player)
		{
			SEMan sEMan = ((Character)player).GetSEMan();
			if (sEMan == null)
			{
				return 1f;
			}
			StatusEffect statusEffect = sEMan.GetStatusEffect(SEMan.s_statusEffectRested);
			SE_Stats val = (SE_Stats)(object)((statusEffect is SE_Stats) ? statusEffect : null);
			if (val == null || val.m_staminaRegenMultiplier <= 1f)
			{
				return 1f;
			}
			float num = 1f;
			sEMan.ModifyStaminaRegen(ref num);
			if (num <= 0f)
			{
				return 1f;
			}
			return Mathf.Max(0f, num - (val.m_staminaRegenMultiplier - 1f)) / num;
		}

		private static void Postfix(Player __instance, SavedStamina __state)
		{
			__instance.m_staminaRegen = __state.Regen;
			__instance.m_staminaRegenTimeMultiplier = __state.TimeMultiplier;
		}
	}
	[HarmonyPatch(typeof(Player), "CheckRun")]
	public static class PlayerCheckRunRoadPatch
	{
		private static Collider s_lastGround;

		private static bool s_lastGroundIsPiece;

		private static void Prefix(Player __instance, out float __state)
		{
			__state = __instance.m_runStaminaDrain;
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && IsOnRoad(__instance))
			{
				__instance.m_runStaminaDrain = __state * Mathf.Max(0f, Plugin.RoadRunStaminaMultiplier.Value);
			}
		}

		private static void Postfix(Player __instance, float __state)
		{
			__instance.m_runStaminaDrain = __state;
		}

		private static bool IsOnRoad(Player player)
		{
			if (!((Character)player).IsOnGround())
			{
				return false;
			}
			Collider lastGroundCollider = ((Character)player).GetLastGroundCollider();
			if ((Object)(object)lastGroundCollider == (Object)null)
			{
				return false;
			}
			if ((Object)(object)lastGroundCollider != (Object)(object)s_lastGround)
			{
				s_lastGround = lastGroundCollider;
				s_lastGroundIsPiece = (Object)(object)((Component)lastGroundCollider).GetComponentInParent<Piece>() != (Object)null;
			}
			if (!s_lastGroundIsPiece)
			{
				return IsOnHoePath((Character)(object)player);
			}
			return true;
		}

		internal static bool IsOnHoePath(Character character)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!character.IsOnGround())
			{
				return false;
			}
			Collider lastGroundCollider = character.GetLastGroundCollider();
			if ((Object)(object)lastGroundCollider == (Object)null)
			{
				return false;
			}
			return IsHoePaint(((Component)lastGroundCollider).GetComponent<Heightmap>(), ((Component)character).transform.position);
		}

		internal static bool IsHoePathAt(Vector3 worldPos)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return IsHoePaint(Heightmap.FindHeightmap(worldPos), worldPos);
		}

		private static bool IsHoePaint(Heightmap heightmap, Vector3 worldPos)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)heightmap == (Object)null)
			{
				return false;
			}
			try
			{
				Color paintMask = heightmap.GetPaintMask(worldPos);
				return (paintMask.r > 0.5f || paintMask.b > 0.5f) && paintMask.g < 0.5f;
			}
			catch
			{
				return false;
			}
		}
	}
	[HarmonyPatch]
	public static class FasterWeaponEquipPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Player), "QueueEquipAction", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Player), "QueueUnequipAction", (Type[])null, (Type[])null);
		}

		private static void Postfix(Player __instance, ItemData item)
		{
			if (item == null || !IsWeaponLike(item))
			{
				return;
			}
			List<MinorActionData> list = ClearActionQueuePatch.ActionQueueRef.Invoke(__instance);
			if (list != null && list.Count != 0)
			{
				MinorActionData val = list[list.Count - 1];
				if (val != null && val.m_item == item && !(val.m_time > 0f))
				{
					val.m_duration *= Mathf.Max(0f, Plugin.WeaponEquipTimeMultiplier.Value);
				}
			}
		}

		private static bool IsWeaponLike(ItemData item)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Invalid comparison between Unknown and I4
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Invalid comparison between Unknown and I4
			//IL_0011: 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: Invalid comparison between Unknown and I4
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			//IL_0017: 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_001c: Invalid comparison between Unknown and I4
			ItemType itemType = item.m_shared.m_itemType;
			if ((int)itemType <= 15)
			{
				if (itemType - 3 <= 2 || itemType - 14 <= 1)
				{
					goto IL_002a;
				}
			}
			else if ((int)itemType == 19 || (int)itemType == 22)
			{
				goto IL_002a;
			}
			return false;
			IL_002a:
			return true;
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateWeaponLoading")]
	public static class ReloadOnlyWithAmmoPatch
	{
		private static bool Prefix(Player __instance, ItemData weapon)
		{
			if (!Plugin.ReloadOnlyWithAmmo.Value || weapon == null || !weapon.m_shared.m_attack.m_requiresReload)
			{
				return true;
			}
			string ammoType = weapon.m_shared.m_ammoType;
			if (string.IsNullOrEmpty(ammoType))
			{
				return true;
			}
			Inventory inventory = ((Humanoid)__instance).GetInventory();
			if (inventory != null)
			{
				return inventory.GetAmmoItem(ammoType, (string)null) != null;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Player), "CheckRun")]
	public static class PlayerCheckRunReloadFlagPatch
	{
		private static void Prefix()
		{
			ClearActionQueuePatch.s_inCheckRun = true;
		}

		private static void Postfix()
		{
			ClearActionQueuePatch.s_inCheckRun = false;
		}
	}
	[HarmonyPatch(typeof(Player), "GetRunSpeedFactor")]
	public static class PlayerRunSpeedHoePathPatch
	{
		private static void Postfix(Player __instance, ref float __result)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && PlayerCheckRunRoadPatch.IsOnHoePath((Character)(object)__instance))
			{
				float num = (Plugin.IsRested(__instance) ? Plugin.RestedHoePathRunSpeedMultiplier.Value : Plugin.HoePathRunSpeedMultiplier.Value);
				__result *= Mathf.Max(0f, num);
			}
		}
	}
	[HarmonyPatch]
	public static class MountHoePathSpeedPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Character), "GetRunSpeedFactor", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Character), "GetJogSpeedFactor", (Type[])null, (Type[])null);
		}

		private static void Postfix(Character __instance, ref float __result)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null) && !((Object)(object)__instance == (Object)(object)localPlayer) && Plugin.MountHoePathSpeed.Value)
			{
				IDoodadController doodadController = localPlayer.GetDoodadController();
				Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
				if (val != null && !((Object)(object)val.GetCharacter() != (Object)(object)__instance) && PlayerCheckRunRoadPatch.IsOnHoePath(__instance))
				{
					float num = (Plugin.IsRested(localPlayer) ? Plugin.RestedHoePathRunSpeedMultiplier.Value : Plugin.HoePathRunSpeedMultiplier.Value);
					__result *= Mathf.Max(0f, num);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Hud), "UpdateStamina")]
	public static class HudStaminaBurstBarColorPatch
	{
		private const float RegenHoldTime = 0.25f;

		private const float ColorFadeSpeed = 6f;

		private static readonly FieldRef<GuiBar, Color> OriginalColorRef = AccessTools.FieldRefAccess<GuiBar, Color>("m_originalColor");

		private static GuiBar s_bar;

		private static float s_lastStamina = -1f;

		private static float s_regenTimer;

		private static float s_blend;

		private static void Postfix(Hud __instance, Player player, float dt)
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			GuiBar staminaBar2Fast = __instance.m_staminaBar2Fast;
			if ((Object)(object)staminaBar2Fast == (Object)null || (Object)(object)player == (Object)null)
			{
				return;
			}
			if ((Object)(object)staminaBar2Fast != (Object)(object)s_bar)
			{
				s_bar = staminaBar2Fast;
				s_lastStamina = -1f;
				s_regenTimer = 0f;
				s_blend = 0f;
			}
			float stamina = player.GetStamina();
			if (s_lastStamina >= 0f && stamina > s_lastStamina)
			{
				s_regenTimer = 0.25f;
			}
			else
			{
				s_regenTimer -= dt;
			}
			s_lastStamina = stamina;
			float num = ((Plugin.StaminaBurstEnabled.Value && Plugin.StaminaBurstBarColorEnabled.Value) ? (1f - Plugin.GetAfterBurst(player)) : 0f);
			float num2 = ((s_regenTimer > 0f) ? num : 0f);
			float num3 = s_blend;
			s_blend = Mathf.MoveTowards(s_blend, num2, dt * 6f);
			if (s_blend <= 0f)
			{
				if (num3 > 0f)
				{
					staminaBar2Fast.ResetColor();
				}
			}
			else
			{
				staminaBar2Fast.SetColor(Color.Lerp(OriginalColorRef.Invoke(staminaBar2Fast), Plugin.StaminaBurstBarColor.Value, s_blend));
			}
		}
	}
	[HarmonyPatch(typeof(Hud), "UpdateStatusEffects")]
	public static class HudAutoRunIconPatch
	{
		private const string AutoRunIconResource = "AichoEnhancedMovement.autorun.png";

		private const string FollowRoadIconResource = "AichoEnhancedMovement.autorun_road.png";

		private const string AutoRunOnPathIconResource = "AichoEnhancedMovement.autorun_path.png";

		private const string OnPathIconResource = "AichoEnhancedMovement.on_path.png";

		private const float OffPathGraceTime = 0.5f;

		private static StatusEffect s_autoRunEffect;

		private static StatusEffect s_autoRunOnPathEffect;

		private static StatusEffect s_followRoadEffect;

		private static StatusEffect s_onPathEffect;

		private static StatusEffect s_lastShown;

		private static float s_lastOnPathTime = -999f;

		private static float s_lastOnPathAnyTime = -999f;

		private static bool s_onPathWasShown;

		private static void Prefix(List<StatusEffect> statusEffects)
		{
			StatusEffect effectToShow = GetEffectToShow();
			if ((Object)(object)effectToShow != (Object)null)
			{
				if (GetModeGroup(effectToShow) != GetModeGroup(s_lastShown))
				{
					effectToShow.m_isNew = true;
				}
				statusEffects.Insert(0, effectToShow);
			}
			s_lastShown = effectToShow;
			int num;
			if (Plugin.ShowOnPathIcon.Value)
			{
				num = (IsOnPathNow() ? 1 : 0);
				if (num != 0)
				{
					StatusEffect effect = GetEffect(ref s_onPathEffect, "AichoEnhancedMovement.on_path.png", "AichoOnPath", Plugin.T("En sendero", "On path"));
					if ((Object)(object)effect != (Object)null)
					{
						if (!s_onPathWasShown)
						{
							effect.m_isNew = true;
						}
						statusEffects.Insert(((Object)(object)effectToShow != (Object)null) ? 1 : 0, effect);
					}
				}
			}
			else
			{
				num = 0;
			}
			s_onPathWasShown = (byte)num != 0;
		}

		private static bool IsOnPathNow()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			IDoodadController doodadController = localPlayer.GetDoodadController();
			Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
			if (PlayerCheckRunRoadPatch.IsOnHoePath((Character)((val != null && (Object)(object)val.GetCharacter() != (Object)null) ? ((object)val.GetCharacter()) : ((object)localPlayer))))
			{
				s_lastOnPathAnyTime = Time.time;
			}
			return Time.time - s_lastOnPathAnyTime <= 0.5f;
		}

		private static int GetModeGroup(StatusEffect effect)
		{
			if ((Object)(object)effect == (Object)null)
			{
				return 0;
			}
			if (!((Object)(object)effect == (Object)(object)s_followRoadEffect))
			{
				return 1;
			}
			return 2;
		}

		private static StatusEffect GetEffectToShow()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || !Plugin.ShowAutoRunIcon.Value)
			{
				return null;
			}
			if (MountRoadFollow.IsActive || (localPlayer.m_autoRun && SetControlsPatch.s_followRoadsMode))
			{
				return GetEffect(ref s_followRoadEffect, "AichoEnhancedMovement.autorun_road.png", "AichoAutoRunRoad", Plugin.T("Siguiendo camino", "Following path"));
			}
			if (localPlayer.m_autoRun)
			{
				if (PlayerCheckRunRoadPatch.IsOnHoePath((Character)(object)localPlayer))
				{
					s_lastOnPathTime = Time.time;
				}
				if (Time.time - s_lastOnPathTime <= 0.5f)
				{
					return GetEffect(ref s_autoRunOnPathEffect, "AichoEnhancedMovement.autorun_path.png", "AichoAutoRunPath", "Auto Run");
				}
				return GetEffect(ref s_autoRunEffect, "AichoEnhancedMovement.autorun.png", "AichoAutoRun", "Auto Run");
			}
			return null;
		}

		private static StatusEffect GetEffect(ref StatusEffect cached, string resource, string id, string displayName)
		{
			if ((Object)(object)cached != (Object)null)
			{
				cached.m_name = displayName;
				return cached;
			}
			Sprite val = LoadSprite(resource);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			cached = ScriptableObject.CreateInstance<StatusEffect>();
			((Object)cached).name = id;
			cached.m_name = displayName;
			cached.m_icon = val;
			cached.m_isNew = false;
			((Object)cached).hideFlags = (HideFlags)61;
			return cached;
		}

		private static Sprite LoadSprite(string resource)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_008b: 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)
			using Stream stream = typeof(HudAutoRunIconPatch).Assembly.GetManifestResourceStream(resource);
			if (stream == null)
			{
				return null;
			}
			byte[] array;
			using (MemoryStream memoryStream = new MemoryStream())
			{
				stream.CopyTo(memoryStream);
				array = memoryStream.ToArray();
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
			if (!ImageConversion.LoadImage(val, array))
			{
				return null;
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)2;
			((Object)val).hideFlags = (HideFlags)61;
			Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
			((Object)obj).hideFlags = (HideFlags)61;
			return obj;
		}
	}
	[HarmonyPatch(typeof(Player), "ClearActionQueue")]
	public static class ClearActionQueuePatch
	{
		internal static readonly FieldRef<Player, List<MinorActionData>> ActionQueueRef = AccessTools.FieldRefAccess<Player, List<MinorActionData>>("m_actionQueue");

		internal static bool s_inCheckRun;

		internal static bool IsReloadQueued(Player player)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Invalid comparison between Unknown and I4
			List<MinorActionData> list = ActionQueueRef.Invoke(player);
			if (list == null)
			{
				return false;
			}
			foreach (MinorActionData item in list)
			{
				if (item != null && (int)item.m_type == 2)
				{
					return true;
				}
			}
			return false;
		}

		private static bool Prefix(Player __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			List<MinorActionData> list = ActionQueueRef.Invoke(__instance);
			if (list == null)
			{
				return true;
			}
			if (Plugin.PauseSprintToReload.Value && s_inCheckRun && IsReloadQueued(__instance))
			{
				return false;
			}
			foreach (MinorActionData item in list)
			{
				if (Plugin.EquipWhileSprinting.Value && item != null && item.m_animation == "equipping")
				{
					return false;
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Player), "SetControls")]
	public static class SetControlsPatch
	{
		private static readonly FieldRef<Character, Vector3> LookDirRef = AccessTools.FieldRefAccess<Character, Vector3>("m_lookDir");

		private static readonly FieldRef<Character, Vector3> MoveDirRef = AccessTools.FieldRefAccess<Character, Vector3>("m_moveDir");

		private static readonly FieldRef<Character, float> LookTransitionTimeRef = AccessTools.FieldRefAccess<Character, float>("m_lookTransitionTime");

		private static readonly FieldRef<PlayerController, bool> ControllerRunRef = AccessTools.FieldRefAccess<PlayerController, bool>("m_run");

		private static readonly FieldRef<PlayerController, bool> ControllerRunPressedWhileStaminaRef = AccessTools.FieldRefAccess<PlayerController, bool>("m_runPressedWhileStamina");

		private static bool s_lastRun;

		private static bool s_stopAutoRun;

		private static bool s_suppressAutoRunUntilRelease;

		private static bool s_lookDirOverridden;

		private static Vector3 s_savedLookDir;

		private static bool s_lastAutoRunButton;

		internal static bool s_followRoadsMode;

		private static bool s_waitingToResumeSprint;

		internal static bool s_freeLooking;

		private static bool s_returningCamera;

		private static Vector3 s_frameDir;

		private static void Prefix(Player __instance, ref Vector3 movedir, bool attack, bool attackHold, bool secondaryAttack, bool secondaryAttackHold, ref bool run, ref bool autoRun, out bool __state)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (s_suppressAutoRunUntilRelease)
			{
				if (autoRun)
				{
					autoRun = false;
				}
				else
				{
					s_suppressAutoRunUntilRelease = false;
				}
			}
			if ((Object)(object)__instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				MountRoadFollow.BeforeControls(__instance, ref movedir, run, autoRun);
				if (s_freeLooking && __instance.GetDoodadController() is Sadle)
				{
					s_savedLookDir = LookDirRef.Invoke((Character)(object)__instance);
					LookDirRef.Invoke((Character)(object)__instance) = s_frameDir;
					s_lookDirOverridden = true;
				}
			}
			__state = (Object)(object)__instance != (Object)null && Plugin.EnhancedAutoRun.Value && __instance.m_autoRun && movedir.z >= -0.1f;
			if (__state && Plugin.StopOnAttack.Value && (attack || attackHold || secondaryAttack || secondaryAttackHold) && !((Character)__instance).InPlaceMode())
			{
				__state = false;
			}
			if ((__state & autoRun) && !s_lastAutoRunButton && Plugin.AutoRunStopWithKey.Value && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && !(__instance.GetDoodadController() is Sadle) && (Plugin.AutoRunFollowRoads.Value && IsFollowRoadsModifierHeld()) == s_followRoadsMode)
			{
				__state = false;
				s_stopAutoRun = true;
				s_suppressAutoRunUntilRelease = true;
			}
			if (run && Plugin.PauseSprintToReload.Value && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && ClearActionQueuePatch.IsReloadQueued(__instance))
			{
				run = false;
			}
			if (s_waitingToResumeSprint && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				if (ZInput.GetButtonDown("Run") || ZInput.GetButtonDown("JoyRun"))
				{
					s_waitingToResumeSprint = false;
				}
				else
				{
					run = false;
				}
			}
		}

		private static void Postfix(Player __instance, Vector3 movedir, bool run, bool autoRun, bool __state)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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_00bf: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: 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_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: 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)
			if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			if (s_lookDirOverridden)
			{
				LookDirRef.Invoke((Character)(object)__instance) = s_savedLookDir;
				s_lookDirOverridden = false;
			}
			bool flag = __state;
			if (flag)
			{
				__instance.m_autoRun = true;
			}
			if (s_stopAutoRun)
			{
				s_stopAutoRun = false;
				__instance.m_autoRun = false;
			}
			UpdateFollowRoadsMode(__instance, autoRun);
			UpdateResumeSprint(__instance, run, flag);
			Vector3 val = Flatten(LookDirRef.Invoke((Character)(object)__instance));
			UpdateFreeLook(__instance, val, flag);
			if (MountRoadFollow.IsActive)
			{
				if (s_freeLooking)
				{
					MountRoadFollow.AfterControls(__instance, s_frameDir, movedir);
					s_frameDir = AutoRunRoadFollow.SteerDirection(s_frameDir, Time.deltaTime);
				}
				else
				{
					MountRoadFollow.AfterControls(__instance, s_returningCamera ? s_frameDir : val, movedir);
				}
			}
			else if (flag && s_followRoadsMode && !s_returningCamera)
			{
				if (s_freeLooking)
				{
					AutoRunRoadFollow.UpdateTarget((Character)(object)__instance, s_frameDir, movedir);
					s_frameDir = AutoRunRoadFollow.SteerDirection(s_frameDir, Time.deltaTime);
				}
				else
				{
					AutoRunRoadFollow.UpdateTarget((Character)(object)__instance, val, movedir);
				}
			}
			else
			{
				AutoRunRoadFollow.Reset();
			}
			bool flag2 = s_freeLooking || s_returningCamera;
			Vector3 val2 = (flag2 ? s_frameDir : val);
			Vector3 val3 = Vector3.Cross(Vector3.up, val2);
			if (flag)
			{
				Vector3 val4 = val2 + movedir.x * val3;
				val4.y = 0f;
				if (((Vector3)(ref val4)).magnitude > 0.1f)
				{
					((Vector3)(ref val4)).Normalize();
					MoveDirRef.Invoke((Character)(object)__instance) = val4;
				}
			}
			else if (flag2 && !((Character)__instance).IsAttached())
			{
				MoveDirRef.Invoke((Character)(object)__instance) = movedir.z * val2 + movedir.x * val3;
			}
		}

		private static void UpdateFollowRoadsMode(Player player, bool autoRunButton)
		{
			bool num = autoRunButton && !s_lastAutoRunButton;
			s_lastAutoRunButton = autoRunButton;
			if (num)
			{
				s_followRoadsMode = Plugin.AutoRunFollowRoads.Value && IsFollowRoadsModifierHeld();
			}
			if (!player.m_autoRun)
			{
				s_followRoadsMode = false;
			}
		}

		internal static bool IsFollowRoadsModifierHeld()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected I4, but got Unknown
			KeyCode value = Plugin.FollowRoadsModifier.Value;
			if (Input.GetKey(value))
			{
				return true;
			}
			return (value - 303) switch
			{
				1 => Input.GetKey((KeyCode)303), 
				0 => Input.GetKey((KeyCode)304), 
				3 => Input.GetKey((KeyCode)305), 
				2 => Input.GetKey((KeyCode)306), 
				5 => Input.GetKey((KeyCode)307), 
				4 => Input.GetKey((KeyCode)308), 
				_ => false, 
			};
		}

		private static void UpdateResumeSprint(Player player, bool run, bool autoRun)
		{
			bool flag = s_lastRun;
			s_lastRun = run;
			if (!autoRun || !Plugin.AutoRunResumeSprint.Value)
			{
				s_waitingToResumeSprint = false;
				return;
			}
			float stamina = player.GetStamina();
			if (stamina <= 0f)
			{
				if (flag || run)
				{
					s_waitingToResumeSprint = true;
				}
				return;
			}
			bool flag2 = (Plugin.StaminaBurstEnabled.Value ? (Plugin.GetAfterBurst(player) >= 1f) : (stamina >= ((Character)player).GetMaxStamina()));
			if (s_waitingToResumeSprint && flag2)
			{
				s_waitingToResumeSprint = false;
				PlayerController component = ((Component)player).GetComponent<PlayerController>();
				if ((Object)(object)component != (Object)null)
				{
					ControllerRunRef.Invoke(component) = true;
					ControllerRunPressedWhileStaminaRef.Invoke(component) = true;
				}
			}
		}

		private static void UpdateFreeLook(Player player, Vector3 lookDir, bool autoRun)
		{
			//IL_00cd: 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)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			if (IsFreeLookHeld(player))
			{
				if (!s_freeLooking)
				{
					s_freeLooking = true;
					s_returningCamera = false;
					Vector3 val = Flatten(MoveDirRef.Invoke((Character)(object)player));
					IDoodadController doodadController = player.GetDoodadController();
					Sadle val2 = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
					if (val2 != null && (Object)(object)val2.GetCharacter() != (Object)null)
					{
						Vector3 val3 = Flatten(((Component)val2.GetCharacter()).transform.forward);
						s_frameDir = ((((Vector3)(ref val3)).magnitude > 0.1f) ? val3 : lookDir);
					}
					else
					{
						s_frameDir = ((autoRun && ((Vector3)(ref val)).magnitude > 0.1f) ? val : lookDir);
					}
				}
			}
			else if (s_freeLooking)
			{
				s_freeLooking = false;
				float num = Mathf.Max(0f, Plugin.FreeLookReturnTime.Value);
				s_returningCamera = num > 0f;
				((Character)player).SetLookDir(s_frameDir, num);
			}
			else if (s_returningCamera && LookTransitionTimeRef.Invoke((Character)(object)player) <= 0f)
			{
				s_returningCamera = false;
			}
		}

		private static bool IsFreeLookHeld(Player player)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.FreeLookEnabled.Value || !Input.GetKey(Plugin.FreeLookKey.Value))
			{
				return false;
			}
			if (((Character)player).IsDead() || ((Character)player).InPlaceMode())
			{
				return false;
			}
			if (((Character)player).IsAttached() && !(player.GetDoodadController() is Sadle))
			{
				return false;
			}
			if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible())
			{
				return !Minimap.IsOpen();
			}
			return false;
		}

		private static Vector3 Flatten(Vector3 dir)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			dir.y = 0f;
			return ((Vector3)(ref dir)).normalized;
		}
	}
	internal static class AutoRunRoadFollow
	{
		private const float MaxAngle = 60f;

		private const float AngleStep = 5f;

		private const float ManualOverrideTime = 1f;

		private const float OffRoadGraceTime = 1.25f;

		private const int MinScore = 2;

		private static readonly float[] SampleDistances = new float[3] { 2.5f, 4f, 6f };

		private const float SlowSpeed = 4f;

		private const float FastSpeed = 8f;

		private const float MaxLookAheadScale = 2.5f;

		private const float SlowSampleInterval = 0.1f;

		private const float FastSampleInterval = 0.05f;

		private const float SlowSmoothTime = 0.45f;

		private const float FastSmoothTime = 0.25f;

		private const float SlowMaxTurnSpeed = 90f;

		private const float FastMaxTurnSpeed = 160f;

		private const float SlowTargetFilter = 0.35f;

		private const float FastTargetFilter = 0.6f;

		private static readonly FieldRef<Character, Quaternion> LookYawRef = AccessTools.FieldRefAccess<Character, Quaternion>("m_lookYaw");

		private static readonly int[] s_scores = new int[Mathf.RoundToInt(12f) * 2 + 1];

		private static float s_nextSampleTime;

		private static bool s_active;

		private static bool s_hasTarget;

		private static float s_targetYaw;

		private static float s_yawVelocity;

		private static float s_speedT;

		private static float s_lastOnRoadTime = -999f;

		internal static float s_lastManualSteerTime = -999f;

		private const float CenteringProbeAhead = 2f;

		private const float CenteringScanHalfWidth = 6f;

		private const float CenteringScanStep = 0.5f;

		private const float CenteringDistance = 6f;

		private const float MaxCenteringAngle = 25f;

		private const float CenteringGain = 0.7f;

		internal static void Reset()
		{
			s_active = false;
			s_hasTarget = false;
			s_nextSampleTime = 0f;
			s_yawVelocity = 0f;
		}

		internal static bool TryGetTargetDirection(out Vector3 dir)
		{
			//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)
			//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)
			dir = Quaternion.Euler(0f, s_targetYaw, 0f) * Vector3.forward;
			if (s_active)
			{
				return s_hasTarget;
			}
			return false;
		}

		internal static void UpdateTarget(Character mover, Vector3 lookDir, Vector3 movedir, bool isMount = false)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.AutoRunFollowRoads.Value || mover.IsSwimming())
			{
				Reset();
				return;
			}
			if (Mathf.Abs(movedir.x) > 0.1f)
			{
				s_lastManualSteerTime = Time.time;
			}
			if (PlayerCheckRunRoadPatch.IsOnHoePath(mover))
			{
				s_lastOnRoadTime = Time.time;
			}
			if (Time.time - s_lastManualSteerTime < 1f || Time.time - s_lastOnRoadTime > 1.25f)
			{
				Reset();
				return;
			}
			s_active = true;
			if (Time.time < s_nextSampleTime)
			{
				return;
			}
			Vector3 velocity = mover.GetVelocity();
			velocity.y = 0f;
			s_speedT = Mathf.InverseLerp(4f, 8f, ((Vector3)(ref velocity)).magnitude);
			s_nextSampleTime = Time.time + Mathf.Lerp(0.1f, 0.05f, s_speedT);
			float lookAheadScale = Mathf.Clamp(((Vector3)(ref velocity)).magnitude / 4f, 1f, 2.5f);
			float num = Mathf.Atan2(lookDir.x, lookDir.z) * 57.29578f;
			if (isMount && ((Vector3)(ref velocity)).magnitude > 1f)
			{
				num = Mathf.Atan2(velocity.x, velocity.z) * 57.29578f;
			}
			if (FindRoadYaw(((Component)mover).transform.position, num, lookAheadScale, out var targetYaw))
			{
				if (isMount)
				{
					targetYaw += GetCenteringCorrection(((Component)mover).transform.position, num) * 0.7f;
				}
				float num2 = Mathf.Lerp(0.35f, 0.6f, s_speedT);
				s_targetYaw = (s_hasTarget ? Mathf.LerpAngle(s_targetYaw, targetYaw, num2) : targetYaw);
				s_hasTarget = true;
			}
			else
			{
				s_hasTarget = false;
			}
		}

		internal static float GetYawDelta(Player player, float dt)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			float y = ((Quaternion)(ref LookYawRef.Invoke((Character)(object)player))).eulerAngles.y;
			return Mathf.DeltaAngle(y, SmoothTowardsTarget(y, dt));
		}

		internal static Vector3 SteerDirection(Vector3 dir, float dt)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			float currentYaw = Mathf.Atan2(dir.x, dir.z) * 57.29578f;
			return Quaternion.Euler(0f, SmoothTowardsTarget(currentYaw, dt), 0f) * Vector3.forward;
		}

		private static float SmoothTowardsTarget(float currentYaw, float dt)
		{
			if (!s_active || !s_hasTarget || dt <= 0f)
			{
				s_yawVelocity = 0f;
				return currentYaw;
			}
			float num = Mathf.Lerp(0.45f, 0.25f, s_speedT);
			float num2 = Mathf.Lerp(90f, 160f, s_speedT);
			return Mathf.SmoothDampAngle(currentYaw, s_targetYaw, ref s_yawVelocity, num, num2, dt);
		}

		private static float GetCenteringCorrection(Vector3 origin, float headingYaw)
		{
			//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)
			//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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_005b: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Quaternion.Euler(0f, headingYaw, 0f) * Vector3.forward;
			Vector3 val2 = Vector3.Cross(Vector3.up, val);
			Vector3 val3 = origin + val * 2f;
			int num = Mathf.RoundToInt(12f);
			int num2 = int.MaxValue;
			for (int i = 0; i <= num; i++)
			{
				if (num2 != int.MaxValue)
				{
					break;
				}
				if (PlayerCheckRunRoadPatch.IsHoePathAt(val3 + val2 * ((float)i * 0.5f)))
				{
					num2 = i;
				}
				else if (PlayerCheckRunRoadPatch.IsHoePathAt(val3 - val2 * ((float)i * 0.5f)))
				{
					num2 = -i;
				}
			}
			if (num2 == int.MaxValue)
			{
				return 0f;
			}
			int num3 = num2;
			int j = num2;
			while (num3 > -num && PlayerCheckRunRoadPatch.IsHoePathAt(val3 + val2 * ((float)(num3 - 1) * 0.5f)))
			{
				num3--;
			}
			for (; j < num && PlayerCheckRunRoadPatch.IsHoePathAt(val3 + val2 * ((float)(j + 1) * 0.5f)); j++)
			{
			}
			return Mathf.Clamp(Mathf.Atan2((float)(num3 + j) * 0.5f * 0.5f, 6f) * 57.29578f, -25f, 25f);
		}

		private static bool FindRoadYaw(Vector3 origin, float currentYaw, float lookAheadScale, out float targetYaw)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_005b: 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)
			int num = (s_scores.Length - 1) / 2;
			int num2 = 0;
			for (int i = 0; i < s_scores.Length; i++)
			{
				Vector3 val = Quaternion.Euler(0f, currentYaw + (float)(i - num) * 5f, 0f) * Vector3.forward;
				int num3 = 0;
				float[] sampleDistances = SampleDistances;
				foreach (float num4 in sampleDistances)
				{
					if (PlayerCheckRunRoadPatch.IsHoePathAt(origin + val * (num4 * lookAheadScale)))
					{
						num3++;
					}
				}
				s_scores[i] = num3;
				if (num3 > num2)
				{
					num2 = num3;
				}
			}
			targetYaw = currentYaw;
			if (num2 < 2)
			{
				return false;
			}
			int num5 = -1;
			for (int k = 0; k <= num; k++)
			{
				if (num5 >= 0)
				{
					break;
				}
				if (s_scores[num - k] == num2)
				{
					num5 = num - k;
				}
				else if (s_scores[num + k] == num2)
				{
					num5 = num + k;
				}
			}
			int num6 = num5;
			int l = num5;
			while (num6 > 0 && s_scores[num6 - 1] == num2)
			{
				num6--;
			}
			for (; l < s_scores.Length - 1 && s_scores[l + 1] == num2; l++)
			{
			}
			targetYaw = currentYaw + ((float)(num6 + l) * 0.5f - (float)num) * 5f;
			return true;
		}
	}
	internal static class MountRoadFollow
	{
		private const int SpeedStop = 0;

		private const int SpeedTurn = 3;

		private const int SpeedNoChange = 4;

		private static readonly FieldInfo SpeedField = AccessTools.Field(typeof(Sadle), "m_speed");

		private static bool s_lastAutoRunButton;

		internal static bool IsActive { get; private set; }

		internal static void BeforeControls(Player player, ref Vector3 movedir, bool run, bool autoRunButton)
		{
			bool flag = autoRunButton && !s_lastAutoRunButton;
			s_lastAutoRunButton = autoRunButton;
			IDoodadController doodadController = player.GetDoodadController();
			Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
			if (val == null || !val.IsValid())
			{
				IsActive = false;
				return;
			}
			if (flag)
			{
				bool flag2 = Plugin.AutoRunFollowRoads.Value && SetControlsPatch.IsFollowRoadsModifierHeld();
				if (IsActive && flag2 && Plugin.AutoRunStopWithKey.Value)
				{
					IsActive = false;
				}
				else
				{
					IsActive = flag2;
					if (IsActive && !run && IsStopped(val))
					{
						movedir.z = 1f;
					}
				}
			}
			if (movedir.z < -0.5f)
			{
				IsActive = false;
			}
		}

		internal static void AfterControls(Player player, Vector3 lookDir, Vector3 movedir)
		{
			//IL_0030: 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_0044: 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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			IDoodadController doodadController = player.GetDoodadController();
			Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null);
			if (val == null || !val.IsValid())
			{
				IsActive = false;
				return;
			}
			Character character = val.GetCharacter();
			if (!((Object)(object)character == (Object)null))
			{
				AutoRunRoadFollow.UpdateTarget(character, lookDir, movedir, isMount: true);
				Vector3 dir;
				Vector3 val2 = (AutoRunRoadFollow.TryGetTargetDirection(out dir) ? dir : lookDir);
				ZNetView component = ((Component)character).GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null && component.IsValid())
				{
					float skillFactor = ((Character)player).GetSkills().GetSkillFactor((SkillType)110);
					component.InvokeRPC("Controls", new object[3] { val2, 4, skillFactor });
				}
			}
		}

		private static bool IsStopped(Sadle sadle)
		{
			if (SpeedField == null)
			{
				return false;
			}
			int num = Convert.ToInt32(SpeedField.GetValue(sadle));
			if (num != 0)
			{
				return num == 3;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Player), "SetMouseLook")]
	public static class PlayerSetMouseLookPatch
	{
		private static void Prefix(Player __instance, ref Vector2 mouseLook)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !SetControlsPatch.s_freeLooking)
			{
				if (Mathf.Abs(mouseLook.x) > 0.01f)
				{
					AutoRunRoadFollow.s_lastManualSteerTime = Time.time;
					AutoRunRoadFollow.Reset();
				}
				else
				{
					mouseLook.x += AutoRunRoadFollow.GetYawDelta(__instance, Time.deltaTime);
				}
			}
		}
	}
	[HarmonyPatch(typeof(GameCamera), "GetCameraPosition")]
	public static class GameCameraMountStabilizePatch
	{
		private const float HeightSmoothTime = 0.25f;

		private static bool s_initialized;

		private static float s_smoothedY;

		private static float s_yVelocity;

		private static void Postfix(float dt, ref Vector3 pos, ref Quaternion rot)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Player localPlayer = Player.m_localPlayer;
			if (!Plugin.MountStabilizeCamera.Value || (Object)(object)localPlayer == (Object)null || !(localPlayer.GetDoodadController() is Sadle))
			{
				s_initialized = false;
				return;
			}
			rot = Quaternion.LookRotation(((Component)((Character)localPlayer).m_eye).transform.forward, Vector3.up);
			float y = ((Component)localPlayer).transform.position.y;
			if (!s_initialized)
			{
				s_smoothedY = y;
				s_yVelocity = 0f;
				s_initialized = true;
			}
			s_smoothedY = Mathf.SmoothDamp(s_smoothedY, y, ref s_yVelocity, 0.25f, 999f, dt);
			pos.y += s_smoothedY - y;
		}
	}
	[HarmonyPatch(typeof(Player), "Update")]
	public static class CallMountPatch
	{
		private const float CommandGraceTime = 2f;

		private static Tameable s_calledMount;

		private static float s_callTime;

		private const float ResponseDelay = 1.1f;

		private static Character s_respondingMount;

		private static float s_responseTime;

		private const string WhistleResource = "AichoEnhancedMovement.whistle.wav";

		private static AudioClip s_whistleClip;

		private static bool s_whistleLoadFailed;

		private static void Postfix(Player __instance)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				if (Plugin.CallMountEnabled.Value && Input.GetKeyDown(Plugin.CallMountKey.Value) && CanUseKey(__instance))
				{
					PlayWhistle(__instance);
					CallNearestMount(__instance);
				}
				UpdateMountResponse();
				UpdateCalledMount(__instance);
			}
		}

		private static void CallNearestMount(Player player)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			Tameable val = null;
			float num = Mathf.Max(0f, Plugin.CallMountRadius.Value);
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if ((Object)(object)allCharacter == (Object)null || allCharacter.IsDead() || !allCharacter.IsTamed())
				{
					continue;
				}
				Tameable component = ((Component)allCharacter).GetComponent<Tameable>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component.m_saddle == (Object)null) && ((Component)component.m_saddle).gameObject.activeSelf && !component.m_saddle.HaveValidUser())
				{
					float num2 = Vector3.Distance(((Component)allCharacter).transform.position, ((Component)player).transform.position);
					if (num2 < num)
					{
						val = component;
						num = num2;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				((Character)player).Message((MessageType)2, Plugin.T("No hay ninguna montura cerca", "No mount nearby"), 0, (Sprite)null, false);
				return;
			}
			s_calledMount = val;
			s_callTime = Time.time;
			s_respondingMount = ((Component)val).GetComponent<Character>();
			s_responseTime = Time.time + 1.1f;
			if (!IsFollowing(val, player))
			{
				val.Command((Humanoid)(object)player, false);
			}
			((Character)player).Message((MessageType)2, val.GetHoverName() + Plugin.T(" viene en camino", " is on its way"), 0, (Sprite)null, false);
		}

		private static void PlayWhistle(Player player)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Expected O, but got Unknown
			float num = Mathf.Clamp01(Plugin.CallMountSoundVolume.Value);
			if (!(num <= 0f))
			{
				AudioClip val = LoadWhistle();
				if (!((Object)(object)val == (Object)null))
				{
					GameObject val2 = new GameObject("AichoCallMountWhistle");
					val2.transform.position = ((Component)player).transform.position;
					AudioSource obj = val2.AddComponent<AudioSource>();
					obj.clip = val;
					obj.volume = num;
					obj.spatialBlend = 0f;
					obj.outputAudioMixerGroup = GetSfxMixerGroup();
					obj.Play();
					Object.Destroy((Object)val2, val.length + 0.1f);
				}
			}
		}

		private static AudioMixerGroup GetSfxMixerGroup()
		{
			AudioMixer val = (((Object)(object)AudioMan.instance != (Object)null) ? AudioMan.instance.m_masterMixer : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			AudioMixerGroup[] array = val.FindMatchingGroups("SFX");
			if (array == null || array.Length == 0)
			{
				return null;
			}
			return array[0];
		}

		private static AudioClip LoadWhistle()
		{
			if ((Object)(object)s_whistleClip != (Object)null || s_whistleLoadFailed)
			{
				return s_whistleClip;
			}
			try
			{
				byte[] array;
				using (Stream stream = typeof(CallMountPatch).Assembly.GetManifestResourceStream("AichoEnhancedMovement.whistle.wav"))
				{
					using MemoryStream memoryStream = new MemoryStream();
					stream.CopyTo(memoryStream);
					array = memoryStream.ToArray();
				}
				int num = BitConverter.ToInt16(array, 22);
				int num2 = BitConverter.ToInt32(array, 24);
				int num3;
				for (int i = 12; i + 8 <= array.Length; i += 8 + num3)
				{
					string text = Encoding.ASCII.GetString(array, i, 4);
					num3 = BitConverter.ToInt32(array, i + 4);
					if (text == "data")
					{
						int num4 = Mathf.Min(num3, array.Length - i - 8) / 2;
						float[] array2 = new float[num4];
						for (int j = 0; j < num4; j++)
						{
							array2[j] = (float)BitConverter.ToInt16(array, i + 8 + j * 2) / 32768f;
						}
						s_whistleClip = AudioClip.Create("AichoWhistle", num4 / num, num, num2, false);
						s_whistleClip.SetData(array2, 0);
						((Object)s_whistleClip).hideFlags = (HideFlags)61;
						return s_whistleClip;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[CallMount] No se pudo cargar el silbido: " + ex.Message));
			}
			s_whistleLoadFailed = true;
			return null;
		}

		private static void UpdateMountResponse()
		{
			//IL_00aa: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_respondingMount == (Object)null || Time.time < s_responseTime)
			{
				return;
			}
			if (!Plugin.MountRespondsToCall.Value)
			{
				s_respondingMount = null;
				return;
			}
			Character val = s_respondingMount;
			s_respondingMount = null;
			if (val.IsDead())
			{
				return;
			}
			BaseAI component = ((Component)val).GetComponent<BaseAI>();
			Tameable component2 = ((Component)val).GetComponent<Tameable>();
			EffectList val2 = (((Object)(object)component != (Object)null && component.m_idleSound.HasEffects()) ? component.m_idleSound : (((Object)(object)component != (Object)null && component.m_alertedEffects.HasEffects()) ? component.m_alertedEffects : (((Object)(object)component2 != (Object)null) ? component2.m_petEffect : null)));
			if (val2 == null)
			{
				return;
			}
			GameObject[] array = val2.Create(((Component)val).transform.position, ((Component)val).transform.rotation, ((Component)val).transform, 1f, -1, default(ZDOID));
			if (array == null)
			{
				return;
			}
			float num = Mathf.Max(0f, Plugin.CallMountRadius.Value) + 10f;
			GameObject[] array2 = array;
			foreach (GameObject val3 in array2)
			{
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				AudioSource[] componentsInChildren = val3.GetComponentsInChildren<AudioSource>();
				foreach (AudioSource val4 in componentsInChildren)
				{
					val4.spatialBlend = 1f;
					if (val4.maxDistance < num)
					{
						val4.maxDistance = num;
					}
				}
			}
		}

		private static void UpdateCalledMount(Player player)
		{
			//IL_008a: 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)
			if ((Object)(object)s_calledMount == (Object)null)
			{
				return;
			}
			Character component = ((Component)s_calledMount).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || component.IsDead() || ((Character)player).IsDead())
			{
				s_calledMount = null;
				return;
			}
			bool flag = player.GetDoodadController() is Sadle;
			bool flag2 = IsFollowing(s_calledMount, player);
			if (flag || (!flag2 && Time.time - s_callTime > 2f))
			{
				if (flag && flag2)
				{
					s_calledMount.Command((Humanoid)(object)player, false);
				}
				s_calledMount = null;
				return;
			}
			Vector3 val = ((Component)component).transform.position - ((Component)player).transform.position;
			val.y = 0f;
			if (flag2 && ((Vector3)(ref val)).magnitude <= Mathf.Max(3f, Plugin.CallMountArriveDistance.Value))
			{
				s_calledMount.Command((Humanoid)(object)player, false);
				s_calledMount = null;
			}
		}

		private static bool IsFollowing(Tameable tameable, Player player)
		{
			ZNetView component = ((Component)tameable).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				return false;
			}
			return component.GetZDO().GetString(ZDOVars.s_follow, "") == player.GetPlayerName();
		}

		private static bool CanUseKey(Player player)
		{
			if (((Character)player).IsDead() || player.GetDoodadController() is Sadle)
			{
				return false;
			}
			if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible())
			{
				return !Minimap.IsOpen();
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Character), "UpdateRotation")]
	public static class CharacterUpdateRotationPatch
	{
		private static readonly FieldRef<Character, Vector3> MoveDirRef = AccessTools.FieldRefAccess<Character, Vector3>("m_moveDir");

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

		private static bool Prefix(Character __instance, ref float __result)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (!SetControlsPatch.s_freeLooking || (Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			if (MoveDirRef.Invoke(__instance) != Vector3.zero || AlwaysRotateCamera(__instance))
			{
				return true;
			}
			__result = 0f;
			return false;
		}
	}
}