Decompiled source of MutatedBowheadWhalePatternAdditionMod v1.0.5

mutatedwhalephases.dll

Decompiled 13 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using FishNet.Object;
using FishNet.Object.Synchronizing;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[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 MutatedWhalePhases
{
	internal static class BallisticUtils
	{
		public static Vector3 SolveVelocityForFlightTime(Vector3 start, Vector3 end, float flightTime, float gravity)
		{
			//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_000f: 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_0015: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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)
			flightTime = Mathf.Max(flightTime, 0.1f);
			Vector3 val = end - start;
			Vector3 val2 = new Vector3(val.x, 0f, val.z);
			float y = val.y;
			Vector3 val3 = val2 / flightTime;
			float num = y / flightTime + 0.5f * gravity * flightTime;
			return val3 + Vector3.up * num;
		}

		public static Vector3 PositionAtTime(Vector3 start, Vector3 initialVelocity, float gravity, float time)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			Vector3 result = start + initialVelocity * time;
			result.y -= 0.5f * gravity * time * time;
			return result;
		}
	}
	[HarmonyPatch(typeof(PlayerHands))]
	internal static class BoatHandVisualPatch
	{
		private static readonly FieldInfo PlayerField = AccessTools.Field(typeof(PlayerHands), "_player");

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPrefix]
		private static bool BeforeDrivenBoatGetter(PlayerHands __instance, ref Boat __result)
		{
			if (!BowheadWhaleAccess.IsSecondPhaseActive())
			{
				return true;
			}
			object? value = PlayerField.GetValue(__instance);
			Player val = (Player)((value is Player) ? value : null);
			if ((Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)val.Holding.HeldItem))
			{
				return true;
			}
			__result = null;
			return false;
		}
	}
	[HarmonyPatch]
	internal static class BoatItemGatePatch
	{
		private static readonly MethodInfo IsDrivingLocallyGetter = AccessTools.PropertyGetter(typeof(Boat), "IsDrivingLocally");

		private static readonly MethodInfo WantToDriveGetter = AccessTools.PropertyGetter(typeof(Boat), "WantToDrive");

		private static readonly MethodInfo BypassIsDrivingLocallyMethod = AccessTools.Method(typeof(BoatItemGatePatch), "BypassIsDrivingLocally", (Type[])null, (Type[])null);

		private static readonly MethodInfo BypassWantToDriveMethod = AccessTools.Method(typeof(BoatItemGatePatch), "BypassWantToDrive", (Type[])null, (Type[])null);

		private static bool BypassIsDrivingLocally()
		{
			if (!BowheadWhaleAccess.IsSecondPhaseActive())
			{
				return Boat.IsDrivingLocally;
			}
			return false;
		}

		private static bool BypassWantToDrive()
		{
			if (!BowheadWhaleAccess.IsSecondPhaseActive())
			{
				return Boat.WantToDrive;
			}
			return false;
		}

		private static IEnumerable<CodeInstruction> Transpile(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				if (CodeInstructionExtensions.Calls(instruction, IsDrivingLocallyGetter))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)BypassIsDrivingLocallyMethod);
				}
				else if (CodeInstructionExtensions.Calls(instruction, WantToDriveGetter))
				{
					yield return new CodeInstruction(OpCodes.Call, (object)BypassWantToDriveMethod);
				}
				else
				{
					yield return instruction;
				}
			}
		}

		[HarmonyPatch(typeof(PlayerInventory), "DeselectSlotInput")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TranspileDeselectSlotInput(IEnumerable<CodeInstruction> instructions)
		{
			return Transpile(instructions);
		}

		[HarmonyPatch(typeof(PlayerInventory), "SelectSlotInput")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TranspileSelectSlotInput(IEnumerable<CodeInstruction> instructions)
		{
			return Transpile(instructions);
		}

		[HarmonyPatch(typeof(PlayerInventory), "ScrollSlotInput")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TranspileScrollSlotInput(IEnumerable<CodeInstruction> instructions)
		{
			return Transpile(instructions);
		}

		[HarmonyPatch(typeof(PlayerInventory), "ChangeBaitInput")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TranspileChangeBaitInput(IEnumerable<CodeInstruction> instructions)
		{
			return Transpile(instructions);
		}

		[HarmonyPatch(typeof(PlayerHolding), "ScanForGrabbableItem")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TranspileScanForGrabbableItem(IEnumerable<CodeInstruction> instructions)
		{
			return Transpile(instructions);
		}

		[HarmonyPatch(typeof(PlayerHolding), "ScanForInteractable")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TranspileScanForInteractable(IEnumerable<CodeInstruction> instructions)
		{
			return Transpile(instructions);
		}

		[HarmonyPatch(typeof(PlayerPunching), "PunchInput")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TranspilePunchInput(IEnumerable<CodeInstruction> instructions)
		{
			return Transpile(instructions);
		}
	}
	[HarmonyPatch]
	internal static class BoatPhaseTwoPatch
	{
		private static readonly FieldInfo DriverField = AccessTools.Field(typeof(Boat), "_driver");

		[HarmonyPatch(typeof(Boat), "TrySetDriver")]
		[HarmonyPrefix]
		private static bool BeforeTrySetDriver(Boat __instance, Player newDriver)
		{
			if (!BowheadWhaleAccess.IsSecondPhaseActive())
			{
				return true;
			}
			if (Object.op_Implicit((Object)(object)__instance.Driver) && Object.op_Implicit((Object)(object)newDriver))
			{
				return false;
			}
			((SyncVar<Player>)DriverField.GetValue(__instance)).Value = newDriver;
			return false;
		}
	}
	internal static class BowheadWhaleAccess
	{
		private static readonly FieldInfo ActiveWhaleField = typeof(BowheadWhale).GetField("_whale", BindingFlags.Static | BindingFlags.NonPublic);

		public static bool TryGetActiveBoss(out BowheadWhale whale)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Invalid comparison between Unknown and I4
			object? value = ActiveWhaleField.GetValue(null);
			whale = (BowheadWhale)((value is BowheadWhale) ? value : null);
			if ((Object)(object)whale != (Object)null && (int)((Creature)whale).BossType == 2)
			{
				return !((Creature)whale).IsDead;
			}
			return false;
		}

		public static bool IsSecondPhaseActive()
		{
			if (TryGetActiveBoss(out var whale))
			{
				return whale._inSecondPhase.Value;
			}
			return false;
		}
	}
	internal static class DebugKeys
	{
		private static readonly MethodInfo SpawnMutatedWhaleMethod = AccessTools.Method(typeof(MainLava), "SpawnMutatedWhale", (Type[])null, (Type[])null);

		private static readonly FieldInfo IsSpawningWhaleField = AccessTools.Field(typeof(MainLava), "_isSpawningWhale");

		public static void Update()
		{
			Keyboard current = Keyboard.current;
			if (current != null)
			{
				if (((ButtonControl)current.jKey).wasPressedThisFrame)
				{
					TrySpawnWhale();
				}
				if (((ButtonControl)current.kKey).wasPressedThisFrame)
				{
					TrySetBossHpPercent(0.49f);
				}
				if (((ButtonControl)current.lKey).wasPressedThisFrame)
				{
					TrySetBossHpPercent(0.09f);
				}
			}
		}

		private static void TrySpawnWhale()
		{
			if (!((Object)(object)BossManager.Boss != (Object)null))
			{
				MainLava val = Object.FindAnyObjectByType<MainLava>();
				if (!((Object)(object)val == (Object)null) && !(bool)IsSpawningWhaleField.GetValue(val))
				{
					((MonoBehaviour)val).StartCoroutine((IEnumerator)SpawnMutatedWhaleMethod.Invoke(val, null));
				}
			}
		}

		private static void TrySetBossHpPercent(float targetPercent)
		{
			Creature boss = BossManager.Boss;
			if (!((Object)(object)boss == (Object)null) && !boss.IsDead)
			{
				int num = Mathf.Max(1, Mathf.RoundToInt((float)BossManager.BossMaxHp * targetPercent));
				int num2 = boss.Hp - num;
				if (num2 > 0)
				{
					boss.ServerChangeHp(num2);
				}
			}
		}
	}
	[BepInPlugin("community.howtofish.mutatedwhalephases", "Mutated Whale Phases", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "community.howtofish.mutatedwhalephases";

		public const string PluginName = "Mutated Whale Phases";

		public const string PluginVersion = "1.0.0";

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			_harmony = new Harmony("community.howtofish.mutatedwhalephases");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Mutated Whale Phases loaded: lava reflect + third phase patches applied.");
		}

		private void Update()
		{
			DebugKeys.Update();
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch]
	internal static class SecondPhaseLaunchPatch
	{
		private const float MinFlightTime = 3.5f;

		private const float FlightSpeedCap = 40f;

		private const float LaunchHeightBonus = 25f;

		private const float LandingSnapDistance = 10f;

		private const float ScreenShakeDuration = 3f;

		private const float TargetDistanceMultiplier = 4f;

		private static readonly FieldInfo RigField = AccessTools.Field(typeof(PlayerMovement), "_rig");

		private static readonly FieldInfo ExtraGravityForceField = AccessTools.Field(typeof(PlayerMovement), "_extraGravityForce");

		private static readonly FieldInfo PlayerField = AccessTools.Field(typeof(PlayerMovement), "_player");

		private static float GetGravity(PlayerMovement movement)
		{
			return (float)ExtraGravityForceField.GetValue(movement);
		}

		[HarmonyPatch(typeof(BowheadWhale), "OnHealthChange")]
		[HarmonyPostfix]
		private static void AfterOnHealthChange(BowheadWhale __instance, bool asServer)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (asServer && (int)((Creature)__instance).BossType == 2 && __instance._inSecondPhase.Value && !SecondPhaseSequenceState.SequenceTriggered)
			{
				SecondPhaseSequenceState.SequenceTriggered = true;
				((MonoBehaviour)__instance).StartCoroutine(RunLaunchSequence(__instance));
			}
		}

		private static IEnumerator RunLaunchSequence(BowheadWhale whale)
		{
			Vector3 position = ((Component)whale).transform.position;
			Vector3 targetPos = (SecondPhaseSequenceState.TargetPosition = ComputeOpenWaterTarget(position));
			foreach (Player alivePlayer in PlayerManager.AlivePlayers)
			{
				alivePlayer.ScreenShake.ConstantShake(true);
			}
			yield return null;
			LaunchAllPlayers(targetPos);
			LaunchBoatToFollow(targetPos);
			while (SecondPhaseSequenceState.FlyingPlayers.Count > 0)
			{
				yield return null;
			}
			SnapBoatAndPlayersToLanding(targetPos);
			foreach (Player alivePlayer2 in PlayerManager.AlivePlayers)
			{
				alivePlayer2.ScreenShake.ConstantShake(false);
			}
			SecondPhaseWhaleFollowPatch.BeginFollow(whale, BoatManager.Boat);
		}

		private static Vector3 ComputeOpenWaterTarget(Vector3 whalePos)
		{
			//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)
			//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_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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_0025: 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_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			int totalIslands = IslandManager.TotalIslands;
			if (totalIslands <= 0)
			{
				Vector3 val = whalePos - Island.IslandPos;
				Vector3 val2;
				if (!(((Vector3)(ref val)).sqrMagnitude > 1f))
				{
					val2 = Vector3.forward;
				}
				else
				{
					val = whalePos - Island.IslandPos;
					val2 = ((Vector3)(ref val)).normalized;
				}
				Vector3 val3 = val2;
				Vector3 result = Island.IslandPos + val3 * (Island.IslandSize * 4f);
				result.y = WaterManager.WaterHeight;
				return result;
			}
			Vector3 val4 = Vector3.zero;
			int num = 0;
			for (int i = 0; i < totalIslands; i++)
			{
				IslandInfo islandInfo;
				try
				{
					islandInfo = IslandManager.GetIslandInfo(i);
				}
				catch
				{
					continue;
				}
				if (islandInfo != null)
				{
					val4 += islandInfo.IslandPosition;
					num++;
				}
			}
			Vector3 result2 = ((num > 0) ? (val4 / (float)num) : Island.IslandPos);
			result2.y = WaterManager.WaterHeight;
			return result2;
		}

		private static void LaunchAllPlayers(Vector3 targetPos)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			foreach (Player alivePlayer in PlayerManager.AlivePlayers)
			{
				Vector3 position = alivePlayer.Transform.position;
				Vector3 val = targetPos + Vector3.up * 25f;
				float num = Vector3.Distance(position, val);
				float num2 = Mathf.Max(3.5f, num / 40f);
				float gravity = GetGravity(alivePlayer.Movement);
				Vector3 linearVelocity = BallisticUtils.SolveVelocityForFlightTime(position, val, num2, gravity);
				Rigidbody rigidbody = alivePlayer.Rigidbody;
				if ((Object)(object)rigidbody != (Object)null)
				{
					rigidbody.linearVelocity = linearVelocity;
				}
				SecondPhaseSequenceState.FlyingPlayers.Add(alivePlayer);
				SecondPhaseSequenceState.LaunchTime[alivePlayer] = Time.time;
				SecondPhaseSequenceState.FlightDuration[alivePlayer] = num2;
			}
			SecondPhaseSequenceState.PlayersAirborne = true;
		}

		private static void LaunchBoatToFollow(Vector3 targetPos)
		{
			Boat boat = BoatManager.Boat;
			if (!((Object)(object)boat == (Object)null))
			{
				boat.HiddenPhysicsRig.isKinematic = true;
			}
		}

		[HarmonyPatch(typeof(PlayerMovement), "Move")]
		[HarmonyPrefix]
		private static bool BeforeMove(PlayerMovement __instance)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			object? value = PlayerField.GetValue(__instance);
			Player val = (Player)((value is Player) ? value : null);
			if ((Object)(object)val == (Object)null || !SecondPhaseSequenceState.FlyingPlayers.Contains(val))
			{
				return true;
			}
			object? value2 = RigField.GetValue(__instance);
			Rigidbody val2 = (Rigidbody)((value2 is Rigidbody) ? value2 : null);
			if ((Object)(object)val2 == (Object)null)
			{
				return true;
			}
			val2.linearVelocity += Vector3.down * (GetGravity(__instance) * Time.fixedDeltaTime);
			TryLandPlayer(val, val2);
			return false;
		}

		private static void TryLandPlayer(Player player, Rigidbody rig)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			Boat boat = BoatManager.Boat;
			if (!((Object)(object)boat == (Object)null))
			{
				FollowPlayersWithBoat(boat);
				float value;
				float num = (SecondPhaseSequenceState.LaunchTime.TryGetValue(player, out value) ? value : Time.time);
				float value2;
				float num2 = (SecondPhaseSequenceState.FlightDuration.TryGetValue(player, out value2) ? value2 : 3.5f);
				bool num3 = Time.time - num >= num2 + 1.5f;
				Vector3 val = rig.position - boat.HiddenPhysicsRig.position;
				bool flag = ((Vector3)(ref val)).sqrMagnitude <= 100f && rig.position.y <= boat.HiddenPhysicsRig.position.y + 3f;
				if (num3 || flag)
				{
					SecondPhaseSequenceState.FlyingPlayers.Remove(player);
					rig.linearVelocity = Vector3.zero;
				}
			}
		}

		private static void FollowPlayersWithBoat(Boat boat)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_005e: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.zero;
			int num = 0;
			foreach (Player flyingPlayer in SecondPhaseSequenceState.FlyingPlayers)
			{
				val += flyingPlayer.Transform.position;
				num++;
			}
			if (num != 0)
			{
				Vector3 val2 = val / (float)num;
				Vector3 val3 = default(Vector3);
				((Vector3)(ref val3))..ctor(val2.x, WaterManager.WaterHeight, val2.z);
				boat.HiddenPhysicsRig.MovePosition(val3);
			}
		}

		private static void SnapBoatAndPlayersToLanding(Vector3 targetPos)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Boat boat = BoatManager.Boat;
			if ((Object)(object)boat != (Object)null)
			{
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(targetPos.x, WaterManager.WaterHeight, targetPos.z);
				boat.HiddenPhysicsRig.MovePosition(val);
				boat.HiddenPhysicsRig.isKinematic = false;
			}
			SecondPhaseSequenceState.PlayersAirborne = false;
		}
	}
	internal static class SecondPhaseSequenceState
	{
		public static bool SequenceTriggered;

		public static bool PlayersAirborne;

		public static Vector3 TargetPosition;

		public static readonly HashSet<Player> FlyingPlayers = new HashSet<Player>();

		public static readonly Dictionary<Player, float> LaunchTime = new Dictionary<Player, float>();

		public static readonly Dictionary<Player, float> FlightDuration = new Dictionary<Player, float>();

		public static void Reset()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			SequenceTriggered = false;
			PlayersAirborne = false;
			TargetPosition = Vector3.zero;
			FlyingPlayers.Clear();
			LaunchTime.Clear();
			FlightDuration.Clear();
		}
	}
	[HarmonyPatch(typeof(BowheadWhale))]
	internal static class SecondPhaseTargetPriorityPatch
	{
		private const int LethalDamage = 99999;

		private static readonly FieldInfo TargetField = AccessTools.Field(typeof(AttackingFish), "_target");

		private static Player _priorityTarget;

		[HarmonyPatch("UpdateMovement")]
		[HarmonyPostfix]
		private static void AfterUpdateMovement(BowheadWhale __instance)
		{
			if (!BowheadWhaleAccess.IsSecondPhaseActive() || !((NetworkBehaviour)__instance).IsServerInitialized)
			{
				_priorityTarget = null;
				return;
			}
			Player val = (_priorityTarget = FindPlayerInWater());
			if ((Object)(object)val != (Object)null)
			{
				TargetField.SetValue(__instance, val);
			}
		}

		private static Player FindPlayerInWater()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			foreach (Player alivePlayer in PlayerManager.AlivePlayers)
			{
				bool num = (Object)(object)alivePlayer.Movement != (Object)null && alivePlayer.Movement.OnBoat;
				bool flag = alivePlayer.Transform.position.y <= WaterManager.WaterHeight;
				if (!num && flag)
				{
					return alivePlayer;
				}
			}
			return null;
		}

		[HarmonyPatch("DamageOnCollision")]
		[HarmonyPrefix]
		private static bool BeforeDamageOnCollision(BowheadWhale __instance, Player player, Vector3 pos)
		{
			//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)
			if (!BowheadWhaleAccess.IsSecondPhaseActive() || (Object)(object)_priorityTarget == (Object)null || (Object)(object)player != (Object)(object)_priorityTarget)
			{
				return true;
			}
			Server.Instance.HitPlayer(player, 99999, Vector3.zero, pos, (byte)2, (Player)null);
			return false;
		}
	}
	[HarmonyPatch(typeof(BowheadWhale))]
	internal static class SecondPhaseWhaleFollowPatch
	{
		private const float RoarShakeDuration = 3f;

		private const float BowOffsetDistance = 20f;

		private const float MinFlightTime = 2.5f;

		private const float SpeedCap = 60f;

		private static readonly FieldInfo RigField = AccessTools.Field(typeof(Item), "_rig");

		private static readonly FieldInfo JumpsLeftField = AccessTools.Field(typeof(BowheadWhale), "_jumpsLeft");

		private static readonly FieldInfo AddedFlyingGravity2Field = AccessTools.Field(typeof(BowheadWhale), "_addedFlyingGravity2");

		private static readonly MethodInfo FlyMethod = AccessTools.Method(typeof(BowheadWhale), "Fly", (Type[])null, (Type[])null);

		private static readonly MethodInfo MakeNoiseSoundMethod = AccessTools.Method(typeof(BowheadWhale), "MakeNoiseSound", (Type[])null, (Type[])null);

		private static float GetGravity(BowheadWhale whale)
		{
			return (float)AddedFlyingGravity2Field.GetValue(whale);
		}

		public static void BeginFollow(BowheadWhale whale, Boat boat)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0049: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			SecondPhaseWhaleFollowState secondPhaseWhaleFollowState = SecondPhaseWhaleFollowState.Get(whale);
			Vector3 val = ComputeBowTarget(whale, boat);
			secondPhaseWhaleFollowState.Active = true;
			secondPhaseWhaleFollowState.HasSurfaced = false;
			secondPhaseWhaleFollowState.TargetPosition = val;
			secondPhaseWhaleFollowState.IsDescending = false;
			object? value = RigField.GetValue(whale);
			Rigidbody val2 = (Rigidbody)((value is Rigidbody) ? value : null);
			Vector3 val3 = (((Object)(object)val2 != (Object)null) ? val2.worldCenterOfMass : ((Component)whale).transform.position);
			float num = Vector3.Distance(val3, val);
			float flightTime = Mathf.Max(2.5f, num / 60f);
			Vector3 linearVelocity = BallisticUtils.SolveVelocityForFlightTime(val3, val, flightTime, GetGravity(whale));
			JumpsLeftField.SetValue(whale, 1);
			FlyMethod.Invoke(whale, null);
			if ((Object)(object)val2 != (Object)null)
			{
				val2.linearVelocity = linearVelocity;
			}
		}

		private static Vector3 ComputeBowTarget(BowheadWhale whale, Boat boat)
		{
			//IL_0017: 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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//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_0076: 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)
			Vector3 val = (((Object)(object)boat != (Object)null && (Object)(object)boat.VisualBoat != (Object)null) ? boat.VisualBoat.forward : Vector3.forward);
			Vector3 result = (((Object)(object)boat != (Object)null && (Object)(object)boat.VisualBoat != (Object)null) ? boat.VisualBoat.position : ((Component)whale).transform.position) + val * 20f;
			result.y = WaterManager.WaterHeight;
			return result;
		}

		[HarmonyPatch("InitializeMovement")]
		[HarmonyPrefix]
		private static bool BeforeInitializeMovement(BowheadWhale __instance)
		{
			return !SecondPhaseWhaleFollowState.Get(__instance).Active;
		}

		[HarmonyPatch("SetFlying")]
		[HarmonyPrefix]
		private static bool BeforeSetFlying(BowheadWhale __instance)
		{
			//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_0054: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			SecondPhaseWhaleFollowState secondPhaseWhaleFollowState = SecondPhaseWhaleFollowState.Get(__instance);
			if (!secondPhaseWhaleFollowState.Active || secondPhaseWhaleFollowState.HasSurfaced)
			{
				return true;
			}
			object? value = RigField.GetValue(__instance);
			Rigidbody val = (Rigidbody)((value is Rigidbody) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			Vector3 linearVelocity = val.linearVelocity;
			linearVelocity.y -= GetGravity(__instance) * Time.fixedDeltaTime;
			val.linearVelocity = linearVelocity;
			if (!(val.worldCenterOfMass.y <= WaterManager.WaterHeight) || !(linearVelocity.y < -1f))
			{
				secondPhaseWhaleFollowState.IsDescending = false;
				return false;
			}
			if (!secondPhaseWhaleFollowState.IsDescending)
			{
				secondPhaseWhaleFollowState.IsDescending = true;
				secondPhaseWhaleFollowState.DescendStartTime = Time.time;
				return false;
			}
			if (Time.time - secondPhaseWhaleFollowState.DescendStartTime >= 0.6f)
			{
				secondPhaseWhaleFollowState.HasSurfaced = true;
				PlaySplashBurst(val.position, 6, 5f);
				JumpsLeftField.SetValue(__instance, 1);
				FlyMethod.Invoke(__instance, null);
				((MonoBehaviour)__instance).StartCoroutine(RoarAfterSurfacing(__instance, val));
			}
			return false;
		}

		private static IEnumerator RoarAfterSurfacing(BowheadWhale whale, Rigidbody rig)
		{
			foreach (Player alivePlayer in PlayerManager.AlivePlayers)
			{
				alivePlayer.ScreenShake.ConstantShake(true);
			}
			MakeNoiseSoundMethod.Invoke(whale, new object[1] { true });
			PlaySplashBurst(new Vector3(rig.position.x, WaterManager.WaterHeight, rig.position.z), 14, 9f);
			yield return (object)new WaitForSeconds(3f);
			foreach (Player alivePlayer2 in PlayerManager.AlivePlayers)
			{
				alivePlayer2.ScreenShake.ConstantShake(false);
			}
			SecondPhaseWhaleFollowState.Get(whale).Active = false;
		}

		private static void PlaySplashBurst(Vector3 center, int count, float radius)
		{
			//IL_0004: 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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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)
			for (int i = 0; i < count; i++)
			{
				Vector3 val = Random.insideUnitSphere * radius;
				val.y = 0f;
				Vector3 val2 = center + val;
				val2.y = WaterManager.WaterHeight;
				VFXManager.Play("WaterSplash", val2, Vector3.zero);
			}
		}
	}
	internal sealed class SecondPhaseWhaleFollowState
	{
		public bool Active;

		public bool HasSurfaced;

		public Vector3 TargetPosition;

		public bool IsDescending;

		public float DescendStartTime = -1f;

		private static readonly ConditionalWeakTable<BowheadWhale, SecondPhaseWhaleFollowState> States = new ConditionalWeakTable<BowheadWhale, SecondPhaseWhaleFollowState>();

		public static SecondPhaseWhaleFollowState Get(BowheadWhale whale)
		{
			return States.GetOrCreateValue(whale);
		}
	}
	[HarmonyPatch(typeof(BowheadWhale))]
	internal static class ThirdPhasePatch
	{
		private const float ThirdPhaseHpThreshold = 0.1f;

		private const float FleeArrivalDistance = 4f;

		private static readonly FieldInfo RigField = AccessTools.Field(typeof(Item), "_rig");

		private static readonly FieldInfo IsFlyingField = AccessTools.Field(typeof(BowheadWhale), "_isFlying");

		private static readonly FieldInfo IsShootingLavaField = AccessTools.Field(typeof(BowheadWhale), "_isShootingLava");

		private static readonly FieldInfo ShootLavaChanceField = AccessTools.Field(typeof(BowheadWhale), "_shootLavaChance");

		private static readonly FieldInfo LavaCountField = AccessTools.Field(typeof(BowheadWhale), "_lavaCount");

		private static readonly FieldInfo JumpsLeftField = AccessTools.Field(typeof(BowheadWhale), "_jumpsLeft");

		private static readonly FieldInfo FlyForceTowardsPlayerField = AccessTools.Field(typeof(BowheadWhale), "_flyForceTowardsPlayer");

		private static readonly MethodInfo ShootLavaMethod = AccessTools.Method(typeof(BowheadWhale), "ShootLava", (Type[])null, (Type[])null);

		private static readonly MethodInfo FlyMethod = AccessTools.Method(typeof(BowheadWhale), "Fly", (Type[])null, (Type[])null);

		private static readonly MethodInfo OnLandedMethod = AccessTools.Method(typeof(BowheadWhale), "OnLanded", (Type[])null, (Type[])null);

		private const float MaxFallSeconds = 4f;

		[HarmonyPatch("Awake")]
		[HarmonyPostfix]
		private static void AfterAwake(BowheadWhale __instance)
		{
			//IL_0016: 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)
			ThirdPhaseState thirdPhaseState = ThirdPhaseState.Get(__instance);
			if (!thirdPhaseState.SpawnPositionCaptured)
			{
				thirdPhaseState.SpawnPosition = ((Component)__instance).transform.position;
				thirdPhaseState.SpawnPositionCaptured = true;
			}
		}

		[HarmonyPatch("OnHealthChange")]
		[HarmonyPostfix]
		private static void AfterHealthChange(BowheadWhale __instance, int next, bool asServer)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Invalid comparison between Unknown and I4
			if (!asServer || (int)((Creature)__instance).BossType != 2)
			{
				return;
			}
			ThirdPhaseState thirdPhaseState = ThirdPhaseState.Get(__instance);
			if (!thirdPhaseState.PhaseActive && !thirdPhaseState.Resolved)
			{
				float num = (float)next / (float)BossManager.BossMaxHp;
				if (num > 0f && num <= 0.1f)
				{
					thirdPhaseState.PhaseActive = true;
					JumpsLeftField.SetValue(__instance, 1);
				}
			}
		}

		[HarmonyPatch("InitializeMovement")]
		[HarmonyPrefix]
		private static bool BeforeInitializeMovement(BowheadWhale __instance)
		{
			ThirdPhaseState thirdPhaseState = ThirdPhaseState.Get(__instance);
			if (!thirdPhaseState.PhaseActive || thirdPhaseState.Resolved)
			{
				return true;
			}
			if (!(bool)IsFlyingField.GetValue(__instance))
			{
				JumpsLeftField.SetValue(__instance, 1);
				FlyMethod.Invoke(__instance, null);
			}
			if (!(bool)IsShootingLavaField.GetValue(__instance))
			{
				float num = (float)ShootLavaChanceField.GetValue(__instance);
				if (Random.Range(0f, 1f) <= num)
				{
					int num2 = (int)LavaCountField.GetValue(__instance);
					((MonoBehaviour)__instance).StartCoroutine((IEnumerator)ShootLavaMethod.Invoke(__instance, new object[1] { num2 }));
				}
			}
			return false;
		}

		[HarmonyPatch("UpdateMovement")]
		[HarmonyPostfix]
		private static void AfterUpdateMovement(BowheadWhale __instance)
		{
			//IL_0044: 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_004f: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			ThirdPhaseState thirdPhaseState = ThirdPhaseState.Get(__instance);
			if (!thirdPhaseState.PhaseActive || thirdPhaseState.Resolved || !thirdPhaseState.SpawnPositionCaptured || !((NetworkBehaviour)__instance).IsServerInitialized)
			{
				return;
			}
			object? value = RigField.GetValue(__instance);
			Rigidbody val = (Rigidbody)((value is Rigidbody) ? value : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Vector3 val2 = thirdPhaseState.SpawnPosition - val.worldCenterOfMass;
			val2.y = 0f;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			Vector3 val3 = thirdPhaseState.SpawnPosition - val.worldCenterOfMass;
			if (((Vector3)(ref val3)).magnitude <= 4f)
			{
				thirdPhaseState.Resolved = true;
				((NetworkBehaviour)__instance).Despawn(((Component)__instance).gameObject, (DespawnType?)null);
			}
			else if ((bool)IsFlyingField.GetValue(__instance) && !(magnitude < 0.01f))
			{
				Vector3 val4 = val2 / magnitude;
				Vector3 linearVelocity = val.linearVelocity;
				Vector2 val5 = new Vector2(linearVelocity.x, linearVelocity.z);
				float num = ((Vector2)(ref val5)).magnitude;
				float num2 = (float)FlyForceTowardsPlayerField.GetValue(__instance) * 0.5f;
				if (num < num2)
				{
					num = num2;
				}
				Vector3 val6 = val4 * num;
				val.linearVelocity = new Vector3(val6.x, linearVelocity.y, val6.z);
			}
		}

		[HarmonyPatch("SetFlying")]
		[HarmonyPostfix]
		private static void AfterSetFlying(BowheadWhale __instance)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			ThirdPhaseState thirdPhaseState = ThirdPhaseState.Get(__instance);
			if (!thirdPhaseState.PhaseActive || thirdPhaseState.Resolved)
			{
				return;
			}
			if (!(bool)IsFlyingField.GetValue(__instance))
			{
				thirdPhaseState.IsDescending = false;
				return;
			}
			object? value = RigField.GetValue(__instance);
			Rigidbody val = (Rigidbody)((value is Rigidbody) ? value : null);
			if (!((Object)(object)val == (Object)null))
			{
				if (!(val.linearVelocity.y < -1f))
				{
					thirdPhaseState.IsDescending = false;
				}
				else if (!thirdPhaseState.IsDescending)
				{
					thirdPhaseState.IsDescending = true;
					thirdPhaseState.DescendStartTime = Time.time;
				}
				else if (Time.time - thirdPhaseState.DescendStartTime >= 4f)
				{
					thirdPhaseState.IsDescending = false;
					OnLandedMethod.Invoke(__instance, null);
				}
			}
		}

		[HarmonyPatch("OnLanded")]
		[HarmonyPostfix]
		private static void AfterOnLanded(BowheadWhale __instance)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//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_0072: 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)
			ThirdPhaseState thirdPhaseState = ThirdPhaseState.Get(__instance);
			if (!thirdPhaseState.PhaseActive || thirdPhaseState.Resolved)
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position;
			if (!(position.y > WaterManager.WaterHeight + 1f))
			{
				for (int i = 0; i < 6; i++)
				{
					Vector3 val = Random.insideUnitSphere * 4f;
					val.y = 0f;
					Vector3 val2 = position + val;
					val2.y = WaterManager.WaterHeight;
					VFXManager.Play("WaterSplash", val2, Vector3.zero);
				}
			}
		}
	}
	internal sealed class ThirdPhaseState
	{
		public Vector3 SpawnPosition;

		public bool SpawnPositionCaptured;

		public bool PhaseActive;

		public bool Resolved;

		public bool IsDescending;

		public float DescendStartTime = -1f;

		private static readonly ConditionalWeakTable<BowheadWhale, ThirdPhaseState> States = new ConditionalWeakTable<BowheadWhale, ThirdPhaseState>();

		public static ThirdPhaseState Get(BowheadWhale whale)
		{
			return States.GetOrCreateValue(whale);
		}
	}
}