Decompiled source of ValkyrieFlyMount v1.0.14

ValkyrieFlyMount.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using SoftReferenceableAssets;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ValkyrieFlyMount")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ValkyrieFlyMount")]
[assembly: AssemblyCopyright("Copyright ©  2023")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4c60a857-ac79-4677-abf0-ca105c4dbf4e")]
[assembly: AssemblyFileVersion("1.0.14")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.14.0")]
[module: UnverifiableCode]
namespace ValkyrieFlyMount;

[BepInPlugin("shudnal.ValkyrieFlyMount", "Valkyrie Fly Mount", "1.0.14")]
public class ValkyrieFlyMount : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Menu), "OnSkip")]
	public static class Menu_OnSkip_IntroSkip
	{
		private static bool Prefix(Menu __instance)
		{
			if (!isFlyingMountValkyrie)
			{
				return true;
			}
			bool flag = menuTeleportOnSkip.Value && IsLocalPlayerReady(mountedPlayer) && (Object)(object)Game.instance != (Object)null;
			FinishMount(controlledValkyrie, flag, !flag);
			if (flag)
			{
				Game.instance.RequestRespawn(0f, false);
			}
			__instance.Hide();
			return false;
		}
	}

	[HarmonyPatch(typeof(Valkyrie), "Awake")]
	public static class Valkyrie_Awake_MountInitialization
	{
		private static bool Prefix(Valkyrie __instance)
		{
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: 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_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: 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_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_032c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0360: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026c: 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)
			Player spawningPlayer = ValkyrieFlyMount.spawningPlayer;
			if ((Object)(object)spawningPlayer == (Object)null)
			{
				return true;
			}
			ValkyrieFlyMount.spawningPlayer = null;
			__instance.m_nview = ((Component)__instance).GetComponent<ZNetView>();
			__instance.m_animator = ((Component)__instance).GetComponentInChildren<Animator>();
			if (!IsLocalPlayerReady(spawningPlayer) || (Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid() || !__instance.m_nview.IsOwner() || (Object)(object)__instance.m_animator == (Object)null || (Object)(object)__instance.m_attachPoint == (Object)null)
			{
				((Behaviour)__instance).enabled = false;
				return false;
			}
			controlledValkyrie = __instance;
			mountedPlayer = spawningPlayer;
			isFlyingMountValkyrie = true;
			Valkyrie.m_instance = __instance;
			mountInitialized = false;
			isHovering = false;
			currentForce = 0f;
			accelerationMultiplier = 0f;
			accelerationStaminaDepleted = false;
			if (!((Component)__instance).TryGetComponent<Rigidbody>(ref mountBody))
			{
				mountBody = ((Component)__instance).gameObject.AddComponent<Rigidbody>();
			}
			mountBody.useGravity = false;
			mountBody.isKinematic = false;
			__instance.m_startAltitude = 10f;
			__instance.m_textDuration = 0f;
			__instance.m_descentAltitude = 100f;
			__instance.m_attachOffset = new Vector3(-0.1f, 1.5f, 0.1f);
			__instance.m_speed = 10f;
			__instance.m_turnRate = 5f;
			__instance.m_dropHeight = 10f;
			__instance.m_notifiedMultiplayerStart = true;
			Vector3 position = ((Component)spawningPlayer).transform.position;
			position.y += __instance.m_startAltitude;
			((Component)__instance).transform.position = position;
			Vector3 val = default(Vector3);
			Quaternion rotation = default(Quaternion);
			GameCamera.m_instance.GetCameraPosition(Time.unscaledDeltaTime, ref val, ref rotation);
			((Component)__instance).transform.rotation = rotation;
			mountedHud = Hud.instance;
			if ((Object)(object)mountedHud != (Object)null && (Object)(object)mountedHud.m_crosshair != (Object)null)
			{
				crosshairState = ((Behaviour)mountedHud.m_crosshair).enabled;
				((Behaviour)mountedHud.m_crosshair).enabled = false;
			}
			spawningPlayer.m_intro = true;
			__instance.m_targetPoint = new Vector3(0f, ZoneSystem.instance.GetGroundHeight(Vector3.zero) + 150f, 0f);
			LocationInstance val2 = default(LocationInstance);
			if (ZoneSystem.instance.FindClosestLocation("StartTemple", Vector3.zero, ref val2))
			{
				__instance.m_targetPoint = val2.m_position;
			}
			float num = Random.value * (float)Math.PI * 2f;
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(Mathf.Sin(num), 0f, Mathf.Cos(num));
			Vector3 val4 = Vector3.Cross(val3, Vector3.up);
			__instance.m_descentStart = __instance.m_targetPoint + val3 * __instance.m_startDescentDistance + val4 * 200f;
			__instance.m_descentStart.y = __instance.m_descentAltitude;
			Vector3 val5 = __instance.m_targetPoint - __instance.m_descentStart;
			val5.y = 0f;
			((Vector3)(ref val5)).Normalize();
			__instance.m_flyAwayPoint = __instance.m_targetPoint + val5 * __instance.m_startDescentDistance;
			__instance.m_flyAwayPoint.y = __instance.m_startAltitude;
			__instance.SyncPlayer(true);
			mountInitialized = true;
			LogInfo("Setting up Valkyrie mount at " + ((object)((Component)__instance).transform.position/*cast due to .constrained prefix*/).ToString());
			return false;
		}
	}

	[HarmonyPatch(typeof(Valkyrie), "FixedUpdate")]
	public static class Valkyrie_FixedUpdate_ValidateMount
	{
		private static bool Prefix(Valkyrie __instance)
		{
			return __instance != controlledValkyrie || ValidateMount();
		}
	}

	[HarmonyPatch(typeof(Valkyrie), "LateUpdate")]
	public static class Valkyrie_LateUpdate_ValidateMount
	{
		private static bool Prefix(Valkyrie __instance)
		{
			return __instance != controlledValkyrie || ValidateMount();
		}
	}

	[HarmonyPatch(typeof(Valkyrie), "OnDestroy")]
	public static class Valkyrie_OnDestroy_ReleaseMount
	{
		private static void Prefix(Valkyrie __instance)
		{
			if (__instance == controlledValkyrie)
			{
				FinishMount(__instance, destroy: false, protectPlayer: true, flyAway: false);
			}
		}
	}

	[HarmonyPatch(typeof(Valkyrie), "UpdateValkyrie")]
	public static class Valkyrie_UpdateValkyrie_MountControl
	{
		private static bool Prefix(Valkyrie __instance, float dt)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_047d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			if (__instance != controlledValkyrie)
			{
				return true;
			}
			if (!ValidateMount())
			{
				return false;
			}
			if (!isHovering && ZInput.instance != null && (DateTime.Now - ZInput.instance.GetLastInputTimer()).TotalSeconds > 60.0)
			{
				SetPhysicsControl(enabled: false);
				return true;
			}
			SetPhysicsControl(enabled: true);
			__instance.m_timer += dt;
			bool flag = CanOperateValkyrie();
			Vector3 forward = ((Component)__instance).transform.forward;
			Vector3 val = (isHovering ? Vector3.zero : (forward / 4f));
			currentForce = Mathf.MoveTowards(currentForce, 0f, dt);
			if (flag)
			{
				bool flag2 = ZInput.GetButton("Forward") || ZInput.GetJoyLeftStickY() < 0f;
				bool flag3 = ZInput.GetButton("Backward") || ZInput.GetJoyLeftStickY() > 0f;
				if (flag2 && !flag3)
				{
					currentForce = Mathf.MoveTowards(currentForce, 1f, dt * 3f * forwardAccelerationMultiplier.Value);
				}
				else if (flag3 && !flag2)
				{
					val -= forward / 4f;
				}
				if (ZInput.GetButton("Left") || ZInput.GetJoyLeftStickX() < 0f)
				{
					val -= ((Component)__instance).transform.right / (flag2 ? 2f : (flag3 ? 10f : 5f)) * horizontalAccelerationMultiplier.Value;
				}
				if (ZInput.GetButton("Right") || ZInput.GetJoyLeftStickX() > 0f)
				{
					val += ((Component)__instance).transform.right / (flag2 ? 2f : (flag3 ? 10f : 5f)) * horizontalAccelerationMultiplier.Value;
				}
				if (ZInput.GetButton("Jump") || ZInput.GetButton("JoyRTrigger"))
				{
					val.y += (flag2 ? 0.8f : (flag3 ? 0.2f : 0.5f)) * verticalAccelerationMultiplier.Value;
				}
				if (ZInput.GetButton("Crouch") || ZInput.GetButton("JoyLTrigger"))
				{
					val.y -= (flag2 ? 0.8f : (flag3 ? 0.2f : 0.5f)) * verticalAccelerationMultiplier.Value;
				}
				if (hoveringStoppedByMoving.Value && (flag2 || flag3))
				{
					isHovering = false;
				}
			}
			val += forward * currentForce;
			if (((Vector3)(ref val)).magnitude > 1f)
			{
				((Vector3)(ref val)).Normalize();
			}
			accelerationStaminaDepleted |= !((Character)mountedPlayer).HaveStamina(0f);
			bool flag4 = flag && (ZInput.GetButton("Run") || ZInput.GetButton("JoyRun"));
			if (flag4)
			{
				accelerationMultiplier = Mathf.MoveTowards(accelerationMultiplier, 1f, boostAccelerationMultiplier.Value * dt / 10f);
			}
			else
			{
				accelerationMultiplier = Mathf.MoveTowards(accelerationMultiplier, 0f, dt);
				accelerationStaminaDepleted = false;
			}
			float num = ((flag4 && !accelerationStaminaDepleted) ? (1.5f + accelerationMultiplier) : 1f);
			Vector3 val2 = 15f * val * num * forceMultiplier.Value - mountBody.linearVelocity;
			if (((Vector3)(ref val2)).magnitude > 15f)
			{
				val2 = ((Vector3)(ref val2)).normalized * 15f;
			}
			mountBody.AddForce(val2, (ForceMode)2);
			if (flag)
			{
				Vector3 val3 = default(Vector3);
				Quaternion val4 = default(Quaternion);
				GameCamera.m_instance.GetCameraPosition(dt, ref val3, ref val4);
				((Component)__instance).transform.rotation = Quaternion.RotateTowards(((Component)__instance).transform.rotation, val4, __instance.m_turnRate * 15f * dt * rotationMultiplier.Value);
			}
			return false;
		}

		private static void Postfix(Valkyrie __instance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			if (__instance == controlledValkyrie && isFlyingMountValkyrie && !((Object)(object)ZoneSystem.instance == (Object)null))
			{
				Vector3 position = ((Component)__instance).transform.position;
				float num = ZoneSystem.instance.m_waterLevel;
				float num2 = default(float);
				if (ZoneSystem.instance.GetGroundHeight(position, ref num2))
				{
					num = Mathf.Max(num, num2);
				}
				num += 5f;
				position.y = Mathf.Clamp(position.y, num, Mathf.Max(num, maxAltitude.Value));
				((Component)__instance).transform.position = position;
			}
		}
	}

	[HarmonyPatch(typeof(Valkyrie), "DropPlayer")]
	public static class Valkyrie_DropPlayer_Dismount
	{
		private static bool Prefix(Valkyrie __instance, bool destroy)
		{
			if (__instance != controlledValkyrie)
			{
				return true;
			}
			FinishMount(__instance, destroy, protectPlayer: true);
			return false;
		}
	}

	[HarmonyPatch(typeof(Player), "TeleportTo")]
	public static class Player_TeleportTo_TeleportDrop
	{
		private static void Postfix(Player __instance, bool __result)
		{
			if (__result && IsMountedPlayer((Character)(object)__instance))
			{
				controlledValkyrie.DropPlayer(true);
			}
		}
	}

	[HarmonyPatch(typeof(Player), "CheckKeyboardRadialPressed")]
	public static class Player_CheckKeyboardRadialPressed_MountShortcut
	{
		private static bool Prefix(Player __instance, ref bool __result)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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)
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			bool flag = lastMountCommandFrame == Time.frameCount;
			if (!flag && CanOperateValkyrie())
			{
				flag = ((!isFlyingMountValkyrie) ? (CanSummonValkyrie(__instance) && IsShortcutDown(mountShortcut.Value)) : (IsShortcutDown(mountShortcut.Value) || IsShortcutDown(dismountShortcut.Value) || IsShortcutDown(hoverShortcut.Value)));
			}
			if (!flag)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}

	[HarmonyPatch(typeof(Player), "InCutscene")]
	public static class Player_InCutscene_Mount
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			return ReplaceIntroCheck(instructions, original);
		}
	}

	[HarmonyPatch(typeof(Player), "UpdateBiome", new Type[] { typeof(float) })]
	public static class Player_UpdateBiome_PreserveBiomeCalculation
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			return ReplaceIntroCheck(instructions, original);
		}
	}

	[HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })]
	public static class Player_UpdateStats_PreserveStatsCalculation
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			return ReplaceIntroCheck(instructions, original);
		}
	}

	[HarmonyPatch(typeof(EnvMan), "GetEnvironmentOverride")]
	public static class EnvMan_GetEnvironmentOverride_EnableWeatherOnFlight
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			return ReplaceIntroCheck(instructions, original);
		}
	}

	[HarmonyPatch(typeof(Player), "CheckRun")]
	public static class Player_CheckRun_Mount
	{
		private static void Prefix(Player __instance, out float? __state)
		{
			__state = null;
			if (IsMountedPlayer((Character)(object)__instance))
			{
				__state = Game.m_moveStaminaRate;
				Game.m_moveStaminaRate *= 2f;
			}
		}

		private static void Finalizer(float? __state)
		{
			if (__state.HasValue)
			{
				Game.m_moveStaminaRate = __state.Value;
			}
		}
	}

	[HarmonyPatch(typeof(Character), "Jump")]
	public static class Character_Jump_Mount
	{
		private static void Prefix(Character __instance, out float? __state)
		{
			__state = null;
			if (IsMountedPlayer(__instance))
			{
				__state = __instance.m_jumpStaminaUsage;
				__instance.m_jumpStaminaUsage = 0f;
			}
		}

		private static void Finalizer(Character __instance, float? __state)
		{
			if (__state.HasValue && (Object)(object)__instance != (Object)null)
			{
				__instance.m_jumpStaminaUsage = __state.Value;
			}
		}
	}

	[HarmonyPatch(typeof(Character), "Damage")]
	public static class Character_Damage_PlayerProtection
	{
		private static void Prefix(Character __instance, HitData hit)
		{
			if (IsMountedPlayer(__instance) && hit != null)
			{
				Character attacker = hit.GetAttacker();
				if (!((Object)(object)attacker != (Object)null) || !attacker.IsBoss())
				{
					((DamageTypes)(ref hit.m_damage)).Modify(0.1f);
				}
			}
		}
	}

	[HarmonyPatch(typeof(Hud), "UpdateCrosshair")]
	public static class Hud_UpdateCrosshair_ShowBowCrosshair
	{
		[HarmonyPriority(0)]
		private static void Postfix(Hud __instance, Player player)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Invalid comparison between Unknown and I4
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Invalid comparison between Unknown and I4
			if (IsMountedPlayer((Character)(object)player) && !((Object)(object)__instance != (Object)(object)mountedHud) && !((Object)(object)__instance.m_crosshair == (Object)null))
			{
				ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon();
				bool flag = currentWeapon != null && ((int)currentWeapon.m_shared.m_itemType == 4 || (int)currentWeapon.m_shared.m_skillType == 14);
				((Behaviour)__instance.m_crosshair).enabled = crosshairState && flag;
			}
		}
	}

	private const string pluginID = "shudnal.ValkyrieFlyMount";

	private const string pluginName = "Valkyrie Fly Mount";

	internal const string pluginVersion = "1.0.14";

	private readonly Harmony harmony = new Harmony("shudnal.ValkyrieFlyMount");

	private static ConfigEntry<bool> modEnabled;

	private static ConfigEntry<bool> loggingEnabled;

	private static ConfigEntry<KeyboardShortcut> mountShortcut;

	private static ConfigEntry<KeyboardShortcut> dismountShortcut;

	private static ConfigEntry<bool> menuTeleportOnSkip;

	private static ConfigEntry<KeyboardShortcut> hoverShortcut;

	private static ConfigEntry<bool> hoveringStoppedByMoving;

	private static ConfigEntry<float> maxAltitude;

	private static ConfigEntry<float> forceMultiplier;

	private static ConfigEntry<float> rotationMultiplier;

	private static ConfigEntry<float> verticalAccelerationMultiplier;

	private static ConfigEntry<float> horizontalAccelerationMultiplier;

	private static ConfigEntry<float> boostAccelerationMultiplier;

	private static ConfigEntry<float> forwardAccelerationMultiplier;

	internal static ValkyrieFlyMount instance;

	internal static Valkyrie controlledValkyrie;

	private static Player spawningPlayer;

	private static Player mountedPlayer;

	private static Rigidbody mountBody;

	private static Hud mountedHud;

	private static bool mountInitialized;

	private static bool isFlyingMountValkyrie;

	private static bool crosshairState;

	private static bool isHovering;

	private static float currentForce;

	private static float accelerationMultiplier;

	private static bool accelerationStaminaDepleted;

	private static int lastMountCommandFrame = -1;

	private static Player slowFallPlayer;

	private static StatusEffect grantedSlowFall;

	private static float slowFallDropFixedTime;

	private static readonly int slowFallHash = StringExtensionMethods.GetStableHashCode("SlowFall");

	private void Awake()
	{
		instance = this;
		ConfigInit();
		harmony.PatchAll();
		Game.isModded = true;
	}

	private void OnDestroy()
	{
		try
		{
			if (isFlyingMountValkyrie)
			{
				FinishMount(controlledValkyrie, destroy: true, protectPlayer: true);
			}
			((BaseUnityPlugin)this).Config.Save();
		}
		finally
		{
			harmony.UnpatchSelf();
			instance = null;
		}
	}

	public static void LogInfo(object data)
	{
		if ((Object)(object)instance != (Object)null && loggingEnabled != null && loggingEnabled.Value)
		{
			((BaseUnityPlugin)instance).Logger.LogInfo(data);
		}
	}

	private void ConfigInit()
	{
		//IL_0061: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable the mod.");
		loggingEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Logging enabled", false, "Enable logging.");
		mountShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "Mount shortcut", new KeyboardShortcut((KeyCode)116, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Mount shortcut.");
		dismountShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "Disount shortcut", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Dismount shortcut.");
		menuTeleportOnSkip = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Teleport to bed on menu skip", false, "Teleport to current spawn point when using Skip intro menu button.");
		hoverShortcut = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hovering", "Hovering shortcut", new KeyboardShortcut((KeyCode)116, Array.Empty<KeyCode>()), "Hovering shortcut. Press while on valkyrie to stop moving forward automatically.");
		hoveringStoppedByMoving = ((BaseUnityPlugin)this).Config.Bind<bool>("Hovering", "Hovering stopped by moving", true, "If true - moving valkyrie will resume flying forward.\nIf false - only pressing hovering shortcut again will start valkyrie flying forward automatically.");
		maxAltitude = ((BaseUnityPlugin)this).Config.Bind<float>("Misc", "Maximum altitude", 1500f, "Height limit.");
		forceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Misc", "Force multiplier", 1f, "Multiplier of force applied to move Valkyrie. Basically indirect speed multiplier");
		rotationMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Misc", "Rotation multiplier", 1f, "Multiplier of rotation delta. Basically angular velocity");
		verticalAccelerationMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Misc", "Vertical Acceleration multiplier", 1f, "Multiplier of vertical change of speed on Up and Down movement");
		horizontalAccelerationMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Misc", "Horizontal Acceleration multiplier", 1f, "Multiplier of horizontal change of speed on Left or Right movement");
		boostAccelerationMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Misc", "Boost Acceleration multiplier", 1f, "Multiplier of speed of boost speed increase");
		forwardAccelerationMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Misc", "Forward acceleration multiplier", 1f, "Multiplier of speed of regular movement speed increase");
	}

	public void LateUpdate()
	{
		//IL_00e9: 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_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		if (isFlyingMountValkyrie && !ValidateMount())
		{
			return;
		}
		UpdateSlowFall();
		if (!CanOperateValkyrie())
		{
			return;
		}
		if (isFlyingMountValkyrie)
		{
			if (IsShortcutDown(mountShortcut.Value) || IsShortcutDown(dismountShortcut.Value) || (ZInput.GetButton("Use") && ZInput.GetButton("AltPlace")) || (ZInput.GetButton("JoyUse") && ZInput.GetButton("JoyAltPlace")))
			{
				lastMountCommandFrame = Time.frameCount;
				controlledValkyrie.DropPlayer(false);
			}
			else if (IsShortcutDown(hoverShortcut.Value))
			{
				isHovering = !isHovering;
				lastMountCommandFrame = Time.frameCount;
			}
		}
		else if (IsShortcutDown(mountShortcut.Value) || (ZInput.GetButton("AltPlace") && ZInput.GetButton("Crouch") && ZInput.GetButton("Jump")) || (ZInput.GetButton("JoyAltPlace") && ZInput.GetButton("JoyCrouch") && ZInput.GetButton("JoyJump")))
		{
			SpawnValkyrie(Player.m_localPlayer);
		}
	}

	private static bool IsShortcutDown(KeyboardShortcut shortcut)
	{
		//IL_0003: 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_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, true))
		{
			return false;
		}
		foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
		{
			if (!ZInput.GetKey(modifier, true))
			{
				return false;
			}
		}
		return true;
	}

	private static bool IsLocalPlayerReady(Player player)
	{
		return (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer && (Object)(object)((Character)player).m_nview != (Object)null && ((Character)player).m_nview.IsValid() && ((Character)player).m_nview.IsOwner();
	}

	private static bool IsMountedPlayer(Character character)
	{
		return isFlyingMountValkyrie && (Object)(object)controlledValkyrie != (Object)null && (Object)(object)character != (Object)null && (Object)(object)character == (Object)(object)mountedPlayer && (Object)(object)character == (Object)(object)Player.m_localPlayer;
	}

	public static bool CanOperateValkyrie()
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Invalid comparison between Unknown and I4
		Player localPlayer = Player.m_localPlayer;
		if (modEnabled == null || !modEnabled.Value || (int)SystemInfo.graphicsDeviceType == 4 || ZInput.instance == null || !IsLocalPlayerReady(localPlayer) || ((Character)localPlayer).IsDead() || ((Character)localPlayer).InCutscene() || ((Character)localPlayer).IsTeleporting() || (Object)(object)GameCamera.m_instance == (Object)null || (Object)(object)Game.instance == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null || (Object)(object)ZNet.instance == (Object)null || (Object)(object)Hud.instance == (Object)null || (Object)(object)Hud.instance.m_buildUi == (Object)null || ZInput.s_IsRebindActive || Game.instance.IsShuttingDown() || PlayerController.HasInputDelay || UnifiedPopup.IsVisible() || BlockCheckHandler.m_dialogOpen || Hud.InRadial() || TextViewer.IsShowingIntro() || ((Object)(object)TextViewer.instance != (Object)null && TextViewer.instance.IsVisible()))
		{
			return false;
		}
		PlayerController component = ((Component)localPlayer).GetComponent<PlayerController>();
		return (Object)(object)component != (Object)null && component.TakeInput(false) && !component.InInventoryEtc();
	}

	private static bool CanSummonValkyrie(Player player)
	{
		return !isFlyingMountValkyrie && (Object)(object)controlledValkyrie == (Object)null && CanOperateValkyrie() && (Object)(object)player != (Object)null && !((Character)player).IsAttachedToShip() && !((Character)player).IsAttached() && !((Character)player).IsRiding() && !player.IsSleeping() && !((Character)player).InPlaceMode() && !((Character)player).InBed() && !((Character)player).InInterior();
	}

	private void SpawnValkyrie(Player player)
	{
		//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_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Expected O, but got Unknown
		if (!CanSummonValkyrie(player))
		{
			return;
		}
		SoftReference<GameObject> valkyrie = player.m_valkyrie;
		GameObject val = null;
		bool flag = false;
		try
		{
			valkyrie.Load();
			flag = true;
			if ((Object)(object)valkyrie.Asset == (Object)null)
			{
				throw new InvalidOperationException("The Valkyrie prefab could not be loaded.");
			}
			spawningPlayer = player;
			val = Object.Instantiate<GameObject>(valkyrie.Asset);
			if (!mountInitialized || (Object)(object)controlledValkyrie == (Object)null || (Object)(object)((Component)controlledValkyrie).gameObject != (Object)(object)val)
			{
				throw new InvalidOperationException("Valkyrie mount initialization did not complete.");
			}
			controlledValkyrie.m_nview.HoldReferenceTo((IReferenceCounted)(object)valkyrie);
			((Character)player).Heal((((Character)player).GetMaxHealth() - ((Character)player).GetHealth()) * 0.3f, true);
			((Character)player).AddStamina(((Character)player).GetMaxStamina());
			((Character)player).SetCrouch(false);
			lastMountCommandFrame = Time.frameCount;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("Failed to summon the Valkyrie mount: " + ex));
			if (isFlyingMountValkyrie)
			{
				FinishMount(controlledValkyrie, destroy: true, protectPlayer: true);
			}
			else
			{
				if (!((Object)(object)val != (Object)null))
				{
					return;
				}
				Valkyrie component = val.GetComponent<Valkyrie>();
				if ((Object)(object)component != (Object)null)
				{
					DestroyValkyrie(component);
					return;
				}
				ZNetView component2 = val.GetComponent<ZNetView>();
				if ((Object)(object)component2 != (Object)null && component2.IsValid())
				{
					if (component2.IsOwner())
					{
						component2.Destroy();
					}
				}
				else
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}
		finally
		{
			spawningPlayer = null;
			if (flag)
			{
				valkyrie.Release();
			}
		}
	}

	private static bool ValidateMount()
	{
		if (!isFlyingMountValkyrie)
		{
			return false;
		}
		if (modEnabled.Value && (Object)(object)controlledValkyrie != (Object)null && (Object)(object)mountBody != (Object)null && IsLocalPlayerReady(mountedPlayer) && !((Character)mountedPlayer).IsDead() && !((Character)mountedPlayer).IsTeleporting() && (Object)(object)controlledValkyrie.m_nview != (Object)null && controlledValkyrie.m_nview.IsValid() && controlledValkyrie.m_nview.IsOwner() && (Object)(object)ZoneSystem.instance != (Object)null && (Object)(object)ZNet.instance != (Object)null && (Object)(object)Game.instance != (Object)null && !Game.instance.IsShuttingDown())
		{
			return true;
		}
		FinishMount(controlledValkyrie, destroy: true, protectPlayer: true);
		return false;
	}

	private static void RestoreCrosshair()
	{
		if ((Object)(object)mountedHud != (Object)null && (Object)(object)mountedHud.m_crosshair != (Object)null)
		{
			((Behaviour)mountedHud.m_crosshair).enabled = crosshairState;
		}
		mountedHud = null;
	}

	private static void ResetFlightState()
	{
		RestoreCrosshair();
		controlledValkyrie = null;
		mountedPlayer = null;
		mountBody = null;
		mountInitialized = false;
		isFlyingMountValkyrie = false;
		isHovering = false;
		currentForce = 0f;
		accelerationMultiplier = 0f;
		accelerationStaminaDepleted = false;
	}

	private static void SetPhysicsControl(bool enabled)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)mountBody == (Object)null) && mountBody.isKinematic != !enabled)
		{
			if (!enabled)
			{
				mountBody.linearVelocity = Vector3.zero;
				mountBody.angularVelocity = Vector3.zero;
			}
			mountBody.isKinematic = !enabled;
		}
	}

	private static void GrantSlowFall(Player player)
	{
		SEMan sEMan = ((Character)player).GetSEMan();
		slowFallDropFixedTime = Time.fixedTime;
		if (!sEMan.HaveStatusEffect(slowFallHash))
		{
			grantedSlowFall = sEMan.AddStatusEffect(slowFallHash, false, 0, 0f, (short)(-1));
			slowFallPlayer = (((Object)(object)grantedSlowFall != (Object)null) ? player : null);
			if ((Object)(object)grantedSlowFall != (Object)null)
			{
				LogInfo("Cast slow fall");
			}
		}
	}

	private static void UpdateSlowFall()
	{
		if ((Object)(object)grantedSlowFall == (Object)null)
		{
			slowFallPlayer = null;
		}
		else if (!IsLocalPlayerReady(slowFallPlayer) || ((Character)slowFallPlayer).IsDead() || (Object)(object)((Character)slowFallPlayer).GetSEMan().GetStatusEffect(slowFallHash) != (Object)(object)grantedSlowFall)
		{
			grantedSlowFall = null;
			slowFallPlayer = null;
		}
		else if (Time.fixedTime > slowFallDropFixedTime && !IsMountedPlayer((Character)(object)slowFallPlayer) && ((Character)slowFallPlayer).IsOnGround())
		{
			((Character)slowFallPlayer).GetSEMan().RemoveStatusEffect(slowFallHash, true);
			grantedSlowFall = null;
			slowFallPlayer = null;
			LogInfo("Remove slow fall");
		}
	}

	private static void FinishMount(Valkyrie valkyrie, bool destroy, bool protectPlayer, bool flyAway = true)
	{
		//IL_0113: 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_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: 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)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		Player val = mountedPlayer;
		try
		{
			SetPhysicsControl(enabled: false);
			if ((Object)(object)valkyrie != (Object)null)
			{
				valkyrie.m_droppedPlayer = true;
				if ((Object)(object)valkyrie.m_animator != (Object)null)
				{
					valkyrie.m_animator.SetBool("dropped", true);
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				if (IsLocalPlayerReady(val))
				{
					val.SetIntro(false);
					if (!((Character)val).IsDead())
					{
						if ((Object)(object)valkyrie != (Object)null)
						{
							Vector3 forward = ((Component)valkyrie).transform.forward;
							forward.y = 0f;
							if (((Vector3)(ref forward)).sqrMagnitude > 0.001f)
							{
								((Component)val).transform.rotation = Quaternion.LookRotation(forward);
							}
						}
						if (protectPlayer)
						{
							GrantSlowFall(val);
						}
					}
				}
				else
				{
					val.m_intro = false;
				}
			}
			if (!destroy && flyAway && (Object)(object)valkyrie != (Object)null && (Object)(object)ZoneSystem.instance != (Object)null)
			{
				Vector3 val2 = ((Component)valkyrie).transform.forward;
				val2.y = 0f;
				val2 = ((((Vector3)(ref val2)).sqrMagnitude > 0.001f) ? ((Vector3)(ref val2)).normalized : Vector3.forward);
				valkyrie.m_flyAwayPoint = ((Component)valkyrie).transform.position + val2 * 300f;
				float num = Mathf.Max(ZoneSystem.instance.GetGroundHeight(valkyrie.m_flyAwayPoint), ZoneSystem.instance.m_waterLevel);
				valkyrie.m_flyAwayPoint.y = Mathf.Max(num + 150f, ((Component)valkyrie).transform.position.y + 100f);
				valkyrie.m_speed = 15f;
			}
		}
		finally
		{
			if (Valkyrie.m_instance == valkyrie)
			{
				Valkyrie.m_instance = null;
			}
			ResetFlightState();
			if (destroy)
			{
				DestroyValkyrie(valkyrie);
			}
		}
	}

	private static void DestroyValkyrie(Valkyrie valkyrie)
	{
		if ((Object)(object)valkyrie == (Object)null)
		{
			return;
		}
		((Behaviour)valkyrie).enabled = false;
		if ((Object)(object)valkyrie.m_nview != (Object)null && valkyrie.m_nview.IsValid())
		{
			if (valkyrie.m_nview.IsOwner())
			{
				valkyrie.m_nview.Destroy();
			}
		}
		else
		{
			Object.Destroy((Object)(object)((Component)valkyrie).gameObject);
		}
	}

	private static bool InIntroOutsideMount(Character character)
	{
		return (Object)(object)character != (Object)null && !IsMountedPlayer(character) && character.InIntro();
	}

	private static IEnumerable<CodeInstruction> ReplaceIntroCheck(IEnumerable<CodeInstruction> instructions, MethodBase original)
	{
		MethodInfo characterIntro = AccessTools.Method(typeof(Character), "InIntro", (Type[])null, (Type[])null);
		MethodInfo playerIntro = AccessTools.Method(typeof(Player), "InIntro", (Type[])null, (Type[])null);
		MethodInfo replacement = AccessTools.Method(typeof(ValkyrieFlyMount), "InIntroOutsideMount", (Type[])null, (Type[])null);
		bool found = false;
		foreach (CodeInstruction instruction in instructions)
		{
			if (CodeInstructionExtensions.Calls(instruction, characterIntro) || CodeInstructionExtensions.Calls(instruction, playerIntro))
			{
				CodeInstruction patched = new CodeInstruction(instruction);
				patched.opcode = OpCodes.Call;
				patched.operand = replacement;
				found = true;
				yield return patched;
			}
			else
			{
				yield return instruction;
			}
		}
		if (!found && (Object)(object)instance != (Object)null)
		{
			((BaseUnityPlugin)instance).Logger.LogWarning((object)("No intro check found in " + original.DeclaringType.FullName + "." + original.Name + "; leaving the original behavior unchanged."));
		}
	}
}