Decompiled source of GreedySeagulls v1.3.1

BepInEx/plugins/GreedySeagulls.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet;
using FishNet.Broadcast;
using FishNet.Connection;
using FishNet.Object;
using FishNet.Serializing;
using FishNet.Transporting;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.SceneManagement;

[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("GreedySeagulls")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.3.1.0")]
[assembly: AssemblyInformationalVersion("1.3.1")]
[assembly: AssemblyProduct("GreedySeagulls")]
[assembly: AssemblyTitle("GreedySeagulls")]
[assembly: AssemblyVersion("1.3.1.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 GreedySeagulls
{
	public static class Birds
	{
		private static readonly List<Bird> _all = new List<Bird>();

		public static IReadOnlyList<Bird> All => _all;

		public static void Add(Bird bird)
		{
			if ((Object)(object)bird != (Object)null && !_all.Contains(bird))
			{
				_all.Add(bird);
				BirdScale.Apply(bird);
			}
		}

		public static void Remove(Bird bird)
		{
			if (!((Object)(object)bird == (Object)null))
			{
				_all.Remove(bird);
				Swarm.Forget(bird);
				BoatLift.Forget(bird);
				GunBird.Forget(bird);
				BirdScale.Forget(bird);
				DiveWatch.Forget(bird);
				PlayerLift.Forget(bird);
			}
		}

		public static void Clear()
		{
			_all.Clear();
			BirdScale.Reset();
		}

		public static void Prune()
		{
			for (int num = _all.Count - 1; num >= 0; num--)
			{
				Bird val = _all[num];
				if (!((Object)(object)val != (Object)null))
				{
					_all.RemoveAt(num);
					Swarm.Forget(val);
					BoatLift.Forget(val);
					GunBird.Forget(val);
					BirdScale.Forget(val);
					DiveWatch.Forget(val);
					PlayerLift.Forget(val);
				}
			}
		}
	}
	public static class BirdScale
	{
		private static readonly Dictionary<Bird, float> _applied = new Dictionary<Bird, float>();

		private static Vector3 _baseScale = Vector3.zero;

		public static void Reset()
		{
			_applied.Clear();
		}

		public static void Forget(Bird bird)
		{
			if ((Object)(object)bird != (Object)null)
			{
				_applied.Remove(bird);
			}
		}

		public static float ScaleOf(Bird bird)
		{
			if (!((Object)(object)bird != (Object)null) || !_applied.TryGetValue(bird, out var value))
			{
				return 1f;
			}
			return value;
		}

		public static void Apply(Bird bird)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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)
			if ((Object)(object)bird == (Object)null || !Plugin.VaryBirdScale.Value || _applied.ContainsKey(bird))
			{
				return;
			}
			if (_baseScale == Vector3.zero)
			{
				Vector3 localScale = ((Component)bird).transform.localScale;
				_baseScale = ((localScale == Vector3.zero) ? Vector3.one : localScale);
			}
			float value = Plugin.MinBirdScale.Value;
			float num = Mathf.Max(value, Plugin.MaxBirdScale.Value);
			float num2 = Mathf.Lerp(value, num, Roll(bird));
			_applied[bird] = num2;
			try
			{
				((Component)bird).transform.localScale = _baseScale * num2;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not scale a seagull: " + ex.Message));
			}
		}

		private static float Roll(Bird bird)
		{
			//IL_0001: 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)
			int num = ((object)((Object)bird).GetEntityId()/*cast due to .constrained prefix*/).GetHashCode();
			NetworkObject networkObject = ((NetworkBehaviour)bird).NetworkObject;
			if ((Object)(object)networkObject != (Object)null && networkObject.ObjectId != 0)
			{
				num = networkObject.ObjectId;
			}
			return (float)new Random(num ^ Plugin.BirdScaleSeed.Value).NextDouble();
		}
	}
	public static class BirdSpawner
	{
		private const float DebugSpawnDistance = 40f;

		public static Bird FindTemplate()
		{
			Bird val = FindLiveBird();
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			foreach (Bird item in Birds.All)
			{
				if ((Object)(object)item != (Object)null)
				{
					return item;
				}
			}
			Bird[] array = Resources.FindObjectsOfTypeAll<Bird>();
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null)
				{
					return array[i];
				}
			}
			return null;
		}

		public static Bird FindLiveBird()
		{
			foreach (Bird item in Birds.All)
			{
				if ((Object)(object)item != (Object)null && !((Creature)item).IsDead && InScene(item))
				{
					return item;
				}
			}
			return null;
		}

		private static bool InScene(Bird bird)
		{
			//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)
			if ((Object)(object)bird != (Object)null)
			{
				Scene scene = ((Component)bird).gameObject.scene;
				return ((Scene)(ref scene)).IsValid();
			}
			return false;
		}

		private static bool KnowsItsAltitude(Bird bird)
		{
			if (InScene(bird))
			{
				return bird.FlyHeigth > 0.01f;
			}
			return false;
		}

		private static float GroundBelow(Vector3 position)
		{
			//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_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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_0029: 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)
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(new Vector3(position.x, position.y + 300f, position.z), Vector3.down, ref val, 600f, LayerMask.op_Implicit(GameInfo.LevelLayer)))
			{
				return ((RaycastHit)(ref val)).point.y;
			}
			return float.NaN;
		}

		private static float WaterLevel(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return WaterManager.GetWaterHeight(position);
			}
			catch
			{
				return 0f;
			}
		}

		private static float SurfaceBelow(Vector3 position)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			float num = GroundBelow(position);
			float num2 = WaterLevel(position);
			if (!float.IsNaN(num) && !(num < num2))
			{
				return num;
			}
			return num2;
		}

		private static float CruiseHeight(Bird preferred)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			Bird val = (KnowsItsAltitude(preferred) ? preferred : FindLiveBird());
			if (KnowsItsAltitude(val))
			{
				float num = val.FlyHeigth - SurfaceBelow(((Component)val).transform.position);
				if (num > 2f)
				{
					return num;
				}
			}
			return Mathf.Max(4f, Plugin.SpawnCruiseHeight.Value);
		}

		private static float AltitudeAt(Vector3 position, Vector3 center, float cruise)
		{
			//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)
			float num = SurfaceBelow(position);
			float num2 = SurfaceBelow(center);
			return Mathf.Max(num, num2) + cruise;
		}

		public static int CountFree()
		{
			int num = 0;
			foreach (Bird item in Birds.All)
			{
				if ((Object)(object)item != (Object)null && !((Creature)item).IsDead && (Object)(object)item.CaughtItem == (Object)null && !BoatLift.IsCrew(item) && !PlayerLift.IsCarrier(item))
				{
					num++;
				}
			}
			return num;
		}

		public static int SpawnRing(Bird template, Vector3 center, Bird altitudeSource, int count, float minDistance, float maxDistance, float heightJitter, List<NetworkObject> track)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_007b: 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)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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)
			//IL_0089: 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_00b1: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_011c: 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)
			if ((Object)(object)template == (Object)null || count <= 0)
			{
				return 0;
			}
			float num = CruiseHeight(altitudeSource);
			float num2 = 360f / (float)count;
			int num3 = 0;
			float num4 = float.NaN;
			for (int i = 0; i < count; i++)
			{
				try
				{
					float num5 = num2 * (float)i + Random.Range((0f - num2) * 0.35f, num2 * 0.35f);
					float num6 = Random.Range(minDistance, maxDistance);
					Vector3 val = Quaternion.Euler(0f, num5, 0f) * Vector3.forward * num6;
					Vector3 val2 = center + val;
					val2.y = AltitudeAt(val2, center, num) + Random.Range(0f - heightJitter, heightJitter);
					if (float.IsNaN(num4))
					{
						num4 = val2.y;
					}
					Vector3 val3 = center - val2;
					val3.y = 0f;
					if (((Vector3)(ref val3)).sqrMagnitude < 0.01f)
					{
						val3 = Vector3.forward;
					}
					GameObject val4 = Object.Instantiate<GameObject>(((Component)template).gameObject, val2, Quaternion.LookRotation(((Vector3)(ref val3)).normalized));
					NetworkObject component = val4.GetComponent<NetworkObject>();
					if ((Object)(object)component == (Object)null)
					{
						Object.Destroy((Object)(object)val4);
						continue;
					}
					InstanceFinder.ServerManager.Spawn(component, (NetworkConnection)null, default(Scene));
					if (!component.IsSpawned)
					{
						Object.Destroy((Object)(object)val4);
						continue;
					}
					track?.Add(component);
					num3++;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Could not spawn a seagull: " + ex.Message));
					break;
				}
			}
			if (num3 > 0)
			{
				Plugin.Log.LogInfo((object)$"Spawned {num3} seagull(s) {num:F1}m above the ground, first one at y {num4:F1}.");
			}
			return num3;
		}

		public static int EnsureFreeBirds(int required, Vector3 center)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			int num = CountFree();
			if (num >= required)
			{
				return 0;
			}
			Bird val = FindTemplate();
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)"There are no seagulls anywhere to copy, so none can be spawned.");
				return 0;
			}
			int count = required - num;
			float num2 = 40f;
			int num3 = SpawnRing(val, center, val, count, num2 * 0.5f, num2, 3f, null);
			Plugin.Log.LogInfo((object)$"{num} free seagull(s) present, spawned {num3} more to reach {required}.");
			return num3;
		}
	}
	public static class BoatLift
	{
		private enum Stage
		{
			Idle,
			Gathering,
			Carrying
		}

		private class CrewState
		{
			public int Index;

			public bool InPosition;
		}

		private static readonly Dictionary<Bird, CrewState> _crew = new Dictionary<Bird, CrewState>();

		private static readonly List<NetworkObject> _spawned = new List<NetworkObject>();

		private static Stage _stage = Stage.Idle;

		private static float _nextAllowedTime;

		private static float _nextCheckTime;

		private static float _stageDeadline;

		private static Vector3 _orbitCenter;

		private static float _orbitRadius;

		private static float _orbitSign = 1f;

		public static bool Active => _stage != Stage.Idle;

		public static bool IsCrew(Bird bird)
		{
			if ((Object)(object)bird != (Object)null)
			{
				return _crew.ContainsKey(bird);
			}
			return false;
		}

		public static void Reset()
		{
			_crew.Clear();
			_spawned.Clear();
			_stage = Stage.Idle;
			_nextAllowedTime = 0f;
			_nextCheckTime = 0f;
			_stageDeadline = 0f;
		}

		public static void Forget(Bird bird)
		{
			if ((Object)(object)bird != (Object)null && _crew.Remove(bird) && _stage != Stage.Idle)
			{
				Plugin.Log.LogInfo((object)"A seagull carrying the boat is gone.");
				if (_crew.Count < Plugin.BoatLiftRequiredBirds.Value)
				{
					Release("the crew got too thin");
				}
			}
		}

		public static void ForceStart()
		{
			_nextAllowedTime = 0f;
			Boat boat = BoatManager.Boat;
			if ((Object)(object)boat == (Object)null || (Object)(object)boat.HiddenPhysicsRig == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Cannot lift the boat: there is no boat.");
			}
			else if (!TryBegin())
			{
				Plugin.Log.LogWarning((object)"Cannot lift the boat right now, even after trying to spawn seagulls.");
			}
		}

		public static void Tick()
		{
			if (_stage == Stage.Idle)
			{
				if (!Plugin.BoatLiftEnabled.Value || Swarm.Active || PlayerLift.Active || Time.time < _nextCheckTime || (Swarm.RealBossActive && !Plugin.BoatLiftAllowDuringBoss.Value))
				{
					return;
				}
				_nextCheckTime = Time.time + Plugin.BoatLiftCheckInterval.Value;
				if (Time.time < _nextAllowedTime)
				{
					return;
				}
				float num = RollChance();
				if (num <= 0f)
				{
					return;
				}
				if (Random.value > num)
				{
					if (Plugin.LogTargeting.Value)
					{
						Plugin.Log.LogInfo((object)$"Boat lift roll failed at {num:P0}.");
					}
				}
				else if (!TryBegin() && Plugin.LogTargeting.Value)
				{
					Plugin.Log.LogInfo((object)"Boat lift roll succeeded but the attempt could not start.");
				}
				return;
			}
			Boat boat = BoatManager.Boat;
			if ((Object)(object)boat == (Object)null || (Object)(object)boat.HiddenPhysicsRig == (Object)null)
			{
				Release("the boat is gone");
				return;
			}
			PruneCrew();
			if (_crew.Count < Plugin.BoatLiftRequiredBirds.Value)
			{
				Release("the crew got too thin");
			}
			else if (_stage == Stage.Gathering)
			{
				if (AllInPosition(boat))
				{
					_stage = Stage.Carrying;
					_stageDeadline = Time.time + Plugin.BoatLiftDuration.Value;
					BeginOrbit(boat);
					Plugin.Log.LogInfo((object)$"{_crew.Count} seagulls have the boat and are hauling it into a circuit of the island at {_orbitRadius:F0}m.");
				}
				else if (Time.time >= _stageDeadline)
				{
					Release("they could not get a grip in time");
				}
			}
			else if (Time.time >= _stageDeadline)
			{
				Release("they got bored");
			}
		}

		private static float RollChance()
		{
			int num = ((PlayerManager.Players == null) ? 1 : PlayerManager.Players.Count);
			return Mathf.Clamp01(Plugin.BoatLiftChancePerPlayer.Value * (float)Mathf.Max(1, num));
		}

		private static Bird PickAnchor(Vector3 boatPos)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			Bird val = null;
			float num = float.MaxValue;
			bool flag = false;
			foreach (Bird item in Birds.All)
			{
				if (!((Object)(object)item == (Object)null) && !((Creature)item).IsDead && !Swarm.IsAttacking(item) && !PlayerLift.IsCarrier(item) && !((Object)(object)item.CaughtItem != (Object)null))
				{
					bool flag2 = (Object)(object)item.AttackingItem == (Object)null;
					float num2 = Vector3.Distance(((Component)item).transform.position, boatPos);
					if (!((Object)(object)val != (Object)null) || ((!flag || flag2) && (flag != flag2 || !(num2 >= num))))
					{
						val = item;
						num = num2;
						flag = flag2;
					}
				}
			}
			return val;
		}

		private static bool TryBegin()
		{
			//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_0034: 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)
			if (Swarm.Active)
			{
				return false;
			}
			Boat boat = BoatManager.Boat;
			if ((Object)(object)boat == (Object)null || (Object)(object)boat.HiddenPhysicsRig == (Object)null)
			{
				return false;
			}
			Vector3 position = boat.HiddenPhysicsRig.position;
			Bird val = PickAnchor(position);
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogInfo((object)"A boat lift was due but there is no seagull available to start it.");
				return false;
			}
			_crew.Clear();
			_spawned.Clear();
			val.SetAttackingFood((Item)null);
			_crew[val] = new CrewState
			{
				Index = 0,
				InPosition = false
			};
			int num = Mathf.Max(0, Plugin.BoatLiftSpawnedBirds.Value);
			if (num > 0)
			{
				BirdSpawner.SpawnRing(val, position, val, num, Plugin.BoatLiftSpawnDistanceMin.Value, Plugin.BoatLiftSpawnDistanceMax.Value, 3f, _spawned);
				foreach (NetworkObject item in _spawned)
				{
					if (!((Object)(object)item == (Object)null))
					{
						Bird component = ((Component)item).GetComponent<Bird>();
						if (!((Object)(object)component == (Object)null) && !_crew.ContainsKey(component))
						{
							component.SetAttackingFood((Item)null);
							_crew[component] = new CrewState
							{
								Index = _crew.Count,
								InPosition = false
							};
						}
					}
				}
			}
			if (_crew.Count < Mathf.Max(1, Plugin.BoatLiftRequiredBirds.Value))
			{
				Plugin.Log.LogWarning((object)$"Only {_crew.Count} seagull(s) could be gathered for the boat, giving up.");
				DespawnHelpers();
				_crew.Clear();
				return false;
			}
			_stage = Stage.Gathering;
			_stageDeadline = Time.time + Plugin.BoatLiftGatherTimeout.Value;
			_nextAllowedTime = Time.time + Plugin.BoatLiftCooldownMinutes.Value * 60f;
			Plugin.Log.LogInfo((object)$"Boat lift started: 1 seagull already here plus {_crew.Count - 1} called in, {_crew.Count} in total.");
			return true;
		}

		private static void DespawnHelpers()
		{
			if (Plugin.BoatLiftDespawnHelpers.Value)
			{
				foreach (NetworkObject item in _spawned)
				{
					if ((Object)(object)item != (Object)null && item.IsSpawned)
					{
						InstanceFinder.ServerManager.Despawn(item, (DespawnType?)null);
					}
				}
			}
			_spawned.Clear();
		}

		private static void PruneCrew()
		{
			List<Bird> list = null;
			foreach (KeyValuePair<Bird, CrewState> item in _crew)
			{
				if ((Object)(object)item.Key == (Object)null || ((Creature)item.Key).IsDead)
				{
					if (list == null)
					{
						list = new List<Bird>();
					}
					list.Add(item.Key);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (Bird item2 in list)
			{
				_crew.Remove(item2);
			}
		}

		private static bool AllInPosition(Boat boat)
		{
			foreach (KeyValuePair<Bird, CrewState> item in _crew)
			{
				if (!item.Value.InPosition)
				{
					return false;
				}
			}
			return true;
		}

		private static Vector3 GripPoint(Boat boat, int index)
		{
			//IL_0061: 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)
			int num = Mathf.Max(1, _crew.Count);
			float num2 = 360f / (float)num * (float)index * (MathF.PI / 180f);
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(Mathf.Sin(num2) * Plugin.BoatLiftRadiusX.Value, Plugin.BoatLiftGripHeight.Value, Mathf.Cos(num2) * Plugin.BoatLiftRadiusZ.Value);
			return ((Component)boat.HiddenPhysicsRig).transform.TransformPoint(val);
		}

		public static void SimulateCrewBird(Bird bird)
		{
			//IL_0034: 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_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_0046: 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_0085: 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_0097: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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_016c: Unknown result type (might be due to invalid IL or missing references)
			Boat boat = BoatManager.Boat;
			if ((Object)(object)boat == (Object)null || (Object)(object)boat.HiddenPhysicsRig == (Object)null || !_crew.TryGetValue(bird, out var value))
			{
				return;
			}
			Vector3 val = GripPoint(boat, value.Index);
			Vector3 position = ((Component)bird).transform.position;
			float num = Vector3.Distance(position, val);
			if (!value.InPosition && num <= Plugin.BoatLiftGripDistance.Value)
			{
				value.InPosition = true;
			}
			if (value.InPosition || _stage == Stage.Carrying)
			{
				((Component)bird).transform.position = Vector3.MoveTowards(position, val, Plugin.BoatLiftHoldSpeed.Value * Time.deltaTime);
				Vector3 val2 = val - ((Component)boat.HiddenPhysicsRig).transform.position;
				val2.y = 0f;
				if (((Vector3)(ref val2)).sqrMagnitude < 0.01f)
				{
					val2 = ((Component)boat.HiddenPhysicsRig).transform.forward;
				}
				((Component)bird).transform.forward = ((Vector3)(ref val2)).normalized;
				bird.SetSpeed(0f);
				bird.SetAnimState((byte)4);
			}
			else
			{
				float num2 = Mathf.Min(Plugin.BoatLiftApproachSpeed.Value, num * 2f + 1f);
				((Component)bird).transform.position = Vector3.MoveTowards(position, val, num2 * Time.deltaTime);
				Vector3 val3 = val - ((Component)bird).transform.position;
				if (((Vector3)(ref val3)).sqrMagnitude > 0.0001f)
				{
					((Component)bird).transform.forward = ((Vector3)(ref val3)).normalized;
				}
				bird.SetSpeed(num2);
				bird.SetAnimState((byte)2);
			}
		}

		private static Vector3 OrbitCenter()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Island.CurIsland != (Object)null)
			{
				return Island.IslandPos;
			}
			if ((Object)(object)Player.LocalPlayer != (Object)null)
			{
				return Player.LocalPlayer.Transform.position;
			}
			return Vector3.zero;
		}

		private static void BeginOrbit(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_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)
			_orbitCenter = OrbitCenter();
			_orbitSign = ((Random.value < 0.5f) ? (-1f) : 1f);
			Vector3 val = boat.HiddenPhysicsRig.position - _orbitCenter;
			val.y = 0f;
			_orbitRadius = Mathf.Clamp(((Vector3)(ref val)).magnitude, Plugin.BoatLiftOrbitRadiusMin.Value, Plugin.BoatLiftOrbitRadiusMax.Value);
		}

		public static void DriveBoat()
		{
			//IL_003f: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00db: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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_011e: 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_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: 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_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: 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_01b0: 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_01bc: Unknown result type (might be due to invalid IL or missing references)
			if (_stage != Stage.Carrying)
			{
				return;
			}
			Boat boat = BoatManager.Boat;
			if (!((Object)(object)boat == (Object)null) && !((Object)(object)boat.HiddenPhysicsRig == (Object)null))
			{
				Rigidbody hiddenPhysicsRig = boat.HiddenPhysicsRig;
				float num = WaterManager.WaterHeight + Plugin.BoatLiftHeight.Value - hiddenPhysicsRig.position.y;
				float value = Plugin.BoatLiftRiseSpeed.Value;
				float y = Mathf.Clamp(num, (0f - value) * 0.5f, value);
				float num2 = Mathf.Clamp01(1f - Mathf.Abs(num) / Mathf.Max(1f, Plugin.BoatLiftHeight.Value));
				_orbitCenter = OrbitCenter();
				Vector3 val = hiddenPhysicsRig.position - _orbitCenter;
				val.y = 0f;
				float magnitude = ((Vector3)(ref val)).magnitude;
				Vector3 val2 = ((magnitude < 0.01f) ? Vector3.forward : (val / magnitude));
				Vector3 val3 = Vector3.Cross(Vector3.up, val2) * _orbitSign;
				float num3 = Mathf.Clamp((_orbitRadius - magnitude) * Plugin.BoatLiftOrbitCorrection.Value, -1f, 1f);
				Vector3 val4 = val3 + val2 * num3;
				Vector3 linearVelocity = ((Vector3)(ref val4)).normalized * (Plugin.BoatLiftCruiseSpeed.Value * num2);
				linearVelocity.y = y;
				hiddenPhysicsRig.linearVelocity = linearVelocity;
				Quaternion rotation = hiddenPhysicsRig.rotation;
				Quaternion val5 = Quaternion.Euler(0f, ((Quaternion)(ref rotation)).eulerAngles.y, 0f);
				Vector3 angularVelocity = DazedUtils.GetAngularVelocityToTarget(hiddenPhysicsRig.rotation, val5) * Plugin.BoatLiftLevelStrength.Value;
				float value2 = Plugin.BoatLiftMaxLevelSpeed.Value;
				if (((Vector3)(ref angularVelocity)).sqrMagnitude > value2 * value2)
				{
					angularVelocity = ((Vector3)(ref angularVelocity)).normalized * value2;
				}
				hiddenPhysicsRig.angularVelocity = angularVelocity;
			}
		}

		private static void Release(string reason)
		{
			if (_stage == Stage.Idle)
			{
				return;
			}
			foreach (KeyValuePair<Bird, CrewState> item in _crew)
			{
				if ((Object)(object)item.Key != (Object)null)
				{
					item.Key.SetSpeed(0f);
				}
			}
			_crew.Clear();
			DespawnHelpers();
			_stage = Stage.Idle;
			_nextCheckTime = Time.time + Plugin.BoatLiftCheckInterval.Value;
			Plugin.Log.LogInfo((object)("The seagulls dropped the boat: " + reason + "."));
		}
	}
	public static class DiveWatch
	{
		private static readonly Dictionary<Bird, float> _blockedSince = new Dictionary<Bird, float>();

		private static readonly Dictionary<Bird, float> _cooldownUntil = new Dictionary<Bird, float>();

		public static void Reset()
		{
			_blockedSince.Clear();
			_cooldownUntil.Clear();
		}

		public static void Forget(Bird bird)
		{
			if ((Object)(object)bird != (Object)null)
			{
				_blockedSince.Remove(bird);
				_cooldownUntil.Remove(bird);
			}
		}

		public static bool OnCooldown(Bird bird)
		{
			if ((Object)(object)bird != (Object)null && _cooldownUntil.TryGetValue(bird, out var value))
			{
				return Time.time < value;
			}
			return false;
		}

		public static void SawTarget(Bird bird)
		{
			if ((Object)(object)bird != (Object)null)
			{
				_blockedSince.Remove(bird);
			}
		}

		public static bool LostTarget(Bird bird, Item item)
		{
			if ((Object)(object)bird == (Object)null)
			{
				return true;
			}
			if (!_blockedSince.TryGetValue(bird, out var value))
			{
				_blockedSince[bird] = Time.time;
				return false;
			}
			if (Time.time - value < Plugin.SightGraceSeconds.Value)
			{
				return false;
			}
			_blockedSince.Remove(bird);
			_cooldownUntil[bird] = Time.time + Plugin.LostSightCooldown.Value;
			string text = (((Object)(object)item != (Object)null) ? ("'" + item.GetName() + "'") : "its target");
			Plugin.Log.LogInfo((object)("A seagull lost sight of " + text + " and gave up the dive."));
			bird.SetAttackingFood((Item)null);
			return true;
		}
	}
	public static class Exclusions
	{
		private static readonly HashSet<string> _names = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<int> _ids = new HashSet<int>();

		private static string _parsedFrom;

		private static readonly HashSet<string> _burstNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static readonly HashSet<int> _burstIds = new HashSet<int>();

		private static string _burstParsedFrom;

		public static void Rebuild()
		{
			string text = Plugin.NeverSteal.Value ?? "";
			if (_parsedFrom == text)
			{
				return;
			}
			_parsedFrom = text;
			_names.Clear();
			_ids.Clear();
			string[] array = text.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length != 0)
				{
					if (int.TryParse(text2, out var result))
					{
						_ids.Add(result);
					}
					else
					{
						_names.Add(Normalise(text2));
					}
				}
			}
			Plugin.Log.LogInfo((object)("Seagulls will never take: " + text));
		}

		public static bool IsBurstWeapon(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			string text = Plugin.BurstWeapons.Value ?? "";
			if (_burstParsedFrom != text)
			{
				_burstParsedFrom = text;
				_burstNames.Clear();
				_burstIds.Clear();
				string[] array = text.Split(',');
				for (int i = 0; i < array.Length; i++)
				{
					string text2 = array[i].Trim();
					if (text2.Length != 0)
					{
						if (int.TryParse(text2, out var result))
						{
							_burstIds.Add(result);
						}
						else
						{
							_burstNames.Add(Normalise(text2));
						}
					}
				}
			}
			if (_burstIds.Contains(item.ID) || _burstNames.Contains(Normalise(((Object)((Component)item).gameObject).name)))
			{
				return true;
			}
			try
			{
				string name = item.GetName();
				return !string.IsNullOrEmpty(name) && _burstNames.Contains(Normalise(name));
			}
			catch (Exception)
			{
				return false;
			}
		}

		public static bool IsExcluded(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			Rebuild();
			if (_names.Count == 0 && _ids.Count == 0)
			{
				return false;
			}
			if (_ids.Contains(item.ID))
			{
				return true;
			}
			if (_names.Contains(Normalise(((Object)((Component)item).gameObject).name)))
			{
				return true;
			}
			try
			{
				string name = item.GetName();
				if (!string.IsNullOrEmpty(name) && _names.Contains(Normalise(name)))
				{
					return true;
				}
			}
			catch (Exception)
			{
			}
			return false;
		}

		private static string Normalise(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return "";
			}
			int num = value.IndexOf("(Clone)", StringComparison.OrdinalIgnoreCase);
			if (num >= 0)
			{
				value = value.Substring(0, num);
			}
			return value.Trim().Replace(" ", "").Replace("_", "")
				.ToLowerInvariant();
		}
	}
	public static class ForceSteal
	{
		public static void Trigger()
		{
			//IL_0061: 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_00ac: 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)
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				Plugin.Log.LogWarning((object)"No local player.");
				return;
			}
			Item val = (((Object)(object)localPlayer.Holding != (Object)null) ? localPlayer.Holding.HeldItem : null);
			string text = "your hands";
			if ((Object)(object)val == (Object)null || ((NetworkBehaviour)val).IsDeinitializing || val.IsDestroying)
			{
				val = NearestGroundTool(localPlayer.Transform.position);
				text = "the ground";
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogInfo((object)"Nothing to steal: your hands are empty and nothing holdable is lying nearby.");
				return;
			}
			Bird val2 = NearestFreeBird(((Component)val).transform.position);
			if ((Object)(object)val2 == (Object)null)
			{
				BirdSpawner.EnsureFreeBirds(1, ((Component)val).transform.position);
				val2 = NearestFreeBird(((Component)val).transform.position);
			}
			if ((Object)(object)val2 == (Object)null)
			{
				Plugin.Log.LogWarning((object)"No free seagull available to send, and none could be spawned.");
				return;
			}
			val2.SetAttackingFood(val);
			Plugin.Log.LogInfo((object)("Sent a seagull after '" + val.GetName() + "' from " + text + "."));
		}

		private static Item NearestGroundTool(Vector3 from)
		{
			//IL_00b4: 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)
			Item result = null;
			float num = float.MaxValue;
			HashSet<Item> hashSet = new HashSet<Item>();
			foreach (KeyValuePair<Transform, Item> item in ItemManager.Items)
			{
				Item value = item.Value;
				if ((Object)(object)value == (Object)null || !hashSet.Add(value))
				{
					continue;
				}
				Targeting.Kind kind = Targeting.Categorize(value);
				if ((kind == Targeting.Kind.Tool || kind == Targeting.Kind.Holdable) && !((NetworkBehaviour)value).IsDeinitializing && !value.IsDestroying && value.IsInteractable && !((Object)(object)value.BirdHolder != (Object)null) && !((Object)(object)value.Bird != (Object)null) && !((Object)(object)value.SyncedHolder != (Object)null) && !((Object)(object)value.Holder != (Object)null))
				{
					float num2 = Vector3.Distance(from, ((Component)value).transform.position);
					if (num2 < num)
					{
						num = num2;
						result = value;
					}
				}
			}
			return result;
		}

		private static Bird NearestFreeBird(Vector3 from)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			Bird result = null;
			float num = float.MaxValue;
			foreach (Bird item in Birds.All)
			{
				if (!((Object)(object)item == (Object)null) && !((Creature)item).IsDead && !((Object)(object)item.CaughtItem != (Object)null) && !BoatLift.IsCrew(item) && !PlayerLift.IsCarrier(item))
				{
					float num2 = Vector3.Distance(from, ((Component)item).transform.position);
					if (num2 < num)
					{
						num = num2;
						result = item;
					}
				}
			}
			return result;
		}
	}
	public static class GunBird
	{
		private class GunState
		{
			public float NextShot;

			public int BurstRemaining;

			public Weapon Weapon;
		}

		private static readonly Dictionary<Bird, GunState> _state = new Dictionary<Bird, GunState>();

		public static void Clear()
		{
			_state.Clear();
		}

		public static void Forget(Bird bird)
		{
			if ((Object)(object)bird != (Object)null)
			{
				_state.Remove(bird);
			}
		}

		public static void Tick(IEnumerable<Bird> birds)
		{
			if (!Plugin.StolenGunsFire.Value || (Object)(object)Player.LocalPlayer == (Object)null)
			{
				return;
			}
			foreach (Bird bird in birds)
			{
				if ((Object)(object)bird == (Object)null || ((Creature)bird).IsDead)
				{
					continue;
				}
				Item caughtItem = bird.CaughtItem;
				Weapon val = (((Object)(object)caughtItem != (Object)null) ? caughtItem.Weapon : null);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (!_state.TryGetValue(bird, out var value))
				{
					value = new GunState
					{
						NextShot = Time.time + RandomInterval(),
						Weapon = val
					};
					_state[bird] = value;
				}
				else if ((Object)(object)value.Weapon != (Object)(object)val)
				{
					value.Weapon = val;
					value.BurstRemaining = 0;
					value.NextShot = Time.time + RandomInterval();
				}
				else if (!(Time.time < value.NextShot))
				{
					if (value.BurstRemaining <= 0)
					{
						value.BurstRemaining = BurstSizeFor(caughtItem, val);
					}
					FireOnce(val);
					value.BurstRemaining--;
					value.NextShot = Time.time + ((value.BurstRemaining > 0) ? Mathf.Max(0.02f, Plugin.BurstShotInterval.Value) : RandomInterval());
				}
			}
		}

		private static int BurstSizeFor(Item carried, Weapon weapon)
		{
			if ((!Plugin.BurstFullAuto.Value || !Refl.IsFullAuto(weapon)) && !Exclusions.IsBurstWeapon(carried))
			{
				return 1;
			}
			int num = Mathf.Max(1, Plugin.BurstShotsMin.Value);
			int num2 = Mathf.Max(num, Plugin.BurstShotsMax.Value);
			return Random.Range(num, num2 + 1);
		}

		private static float RandomInterval()
		{
			float value = Plugin.GunFireIntervalMin.Value;
			float num = Mathf.Max(value, Plugin.GunFireIntervalMax.Value);
			return Random.Range(value, num);
		}

		private static void FireOnce(Weapon weapon)
		{
			//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_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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			Attachments attachments = weapon.Attachments;
			if ((Object)(object)attachments == (Object)null)
			{
				return;
			}
			Transform firePoint = attachments.FirePoint;
			if (!((Object)(object)firePoint == (Object)null))
			{
				WeaponInfo weaponInfo = Refl.GetWeaponInfo(weapon);
				if (weaponInfo != null && !((Object)(object)ProjectileManager.Instance == (Object)null))
				{
					Vector3 val = firePoint.forward + Random.insideUnitSphere * Plugin.GunSpread.Value;
					((Vector3)(ref val)).Normalize();
					ProjectileManager.Instance.AddProjectile(Player.LocalPlayer, weaponInfo, true, firePoint.position, val * weaponInfo.ProjectileForce, 0u, 0u, true);
					weapon.ShootEffects(false);
					AnnounceShot(attachments, firePoint.position);
				}
			}
		}

		private static void AnnounceShot(Attachments attachments, Vector3 position)
		{
			//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)
			string fireSound = attachments.FireSound;
			if (!string.IsNullOrEmpty(fireSound))
			{
				Net.SendGunShot(new GunShotBroadcast
				{
					Position = position,
					Sound = fireSound,
					Count = Mathf.Max(1, attachments.FireSoundCount),
					Medium = attachments.UseMediumSoundDistance,
					Volume = attachments.FireSoundVolume
				});
			}
		}

		public static void PlayShotSound(GunShotBroadcast msg)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(msg.Sound))
			{
				return;
			}
			try
			{
				AudioManager.PlayRandomClipAt(msg.Sound, 1, Mathf.Max(1, msg.Count), msg.Position, false, (AudioDistance)(msg.Medium ? 2 : 3), msg.Volume, 0.1f);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not play a seagull gun shot: " + ex.Message));
			}
		}
	}
	public static class HeldTargetFix
	{
		public static bool GetFlyDirection(Bird bird, ref Vector3 result)
		{
			//IL_0044: 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_0059: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_0102: 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)
			if ((Object)(object)bird == (Object)null)
			{
				return true;
			}
			Item attackingItem = bird.AttackingItem;
			if ((Object)(object)attackingItem == (Object)null)
			{
				return true;
			}
			if (!((Object)(object)attackingItem.Holder != (Object)null) && !((Object)(object)attackingItem.SyncedHolder != (Object)null))
			{
				return true;
			}
			Vector3 val = ((Component)attackingItem).transform.position - ((Component)bird).transform.position;
			if (((NetworkBehaviour)attackingItem).IsDeinitializing || attackingItem.IsDestroying || (Object)(object)attackingItem.BirdHolder != (Object)null || !attackingItem.IsInteractable)
			{
				bird.SetAttackingFood((Item)null);
				return true;
			}
			bool flag = Physics.Raycast(((Component)bird).transform.position, val, Mathf.Max(0f, ((Vector3)(ref val)).magnitude - 0.15f), LayerMask.op_Implicit(GameInfo.LevelLayer));
			if (!flag && Plugin.RequireOpenSkyForHandSteal.Value && Physics.Raycast(((Component)attackingItem).transform.position, Vector3.up, 10f, LayerMask.op_Implicit(GameInfo.LevelLayer)))
			{
				flag = true;
			}
			if (flag)
			{
				if (DiveWatch.LostTarget(bird, attackingItem))
				{
					return true;
				}
				result = val;
				return false;
			}
			DiveWatch.SawTarget(bird);
			result = val;
			return false;
		}
	}
	public struct SwarmBarBroadcast : IBroadcast
	{
		public bool Active;

		public int Current;

		public int Max;

		public uint SpawnTick;

		public uint TotalTicks;
	}
	public struct PlayerLiftBroadcast : IBroadcast
	{
		public int ClientId;

		public int BirdObjectId;

		public bool Grabbed;
	}
	public struct SeagullHandshakeBroadcast : IBroadcast
	{
		public int Version;
	}
	public struct GunShotBroadcast : IBroadcast
	{
		public Vector3 Position;

		public string Sound;

		public int Count;

		public bool Medium;

		public float Volume;
	}
	public static class Net
	{
		private static bool _serializersRegistered;

		private static bool _clientRegistered;

		private static bool _serverRegistered;

		public const int ProtocolVersion = 1;

		public static void RegisterSerializers()
		{
			if (!_serializersRegistered)
			{
				_serializersRegistered = true;
				GenericWriter<SwarmBarBroadcast>.SetWrite((Action<Writer, SwarmBarBroadcast>)delegate(Writer w, SwarmBarBroadcast v)
				{
					w.WriteBoolean(v.Active);
					w.WriteInt32(v.Current);
					w.WriteInt32(v.Max);
					w.WriteUInt32(v.SpawnTick);
					w.WriteUInt32(v.TotalTicks);
				});
				GenericReader<SwarmBarBroadcast>.SetRead((Func<Reader, SwarmBarBroadcast>)((Reader r) => new SwarmBarBroadcast
				{
					Active = r.ReadBoolean(),
					Current = r.ReadInt32(),
					Max = r.ReadInt32(),
					SpawnTick = r.ReadUInt32(),
					TotalTicks = r.ReadUInt32()
				}));
				GenericWriter<PlayerLiftBroadcast>.SetWrite((Action<Writer, PlayerLiftBroadcast>)delegate(Writer w, PlayerLiftBroadcast v)
				{
					w.WriteInt32(v.ClientId);
					w.WriteInt32(v.BirdObjectId);
					w.WriteBoolean(v.Grabbed);
				});
				GenericReader<PlayerLiftBroadcast>.SetRead((Func<Reader, PlayerLiftBroadcast>)((Reader r) => new PlayerLiftBroadcast
				{
					ClientId = r.ReadInt32(),
					BirdObjectId = r.ReadInt32(),
					Grabbed = r.ReadBoolean()
				}));
				GenericWriter<SeagullHandshakeBroadcast>.SetWrite((Action<Writer, SeagullHandshakeBroadcast>)delegate(Writer w, SeagullHandshakeBroadcast v)
				{
					w.WriteInt32(v.Version);
				});
				GenericReader<SeagullHandshakeBroadcast>.SetRead((Func<Reader, SeagullHandshakeBroadcast>)((Reader r) => new SeagullHandshakeBroadcast
				{
					Version = r.ReadInt32()
				}));
				GenericWriter<GunShotBroadcast>.SetWrite((Action<Writer, GunShotBroadcast>)delegate(Writer w, GunShotBroadcast v)
				{
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					w.WriteVector3(v.Position);
					w.WriteString(v.Sound);
					w.WriteInt32(v.Count);
					w.WriteBoolean(v.Medium);
					w.WriteSingle(v.Volume);
				});
				GenericReader<GunShotBroadcast>.SetRead((Func<Reader, GunShotBroadcast>)((Reader r) => new GunShotBroadcast
				{
					Position = r.ReadVector3(),
					Sound = r.ReadString(),
					Count = r.ReadInt32(),
					Medium = r.ReadBoolean(),
					Volume = r.ReadSingle()
				}));
			}
		}

		public static void TryRegisterHandlers()
		{
			if (!((Object)(object)InstanceFinder.NetworkManager == (Object)null))
			{
				RegisterSerializers();
				if (!_clientRegistered && (Object)(object)InstanceFinder.ClientManager != (Object)null)
				{
					_clientRegistered = true;
					InstanceFinder.ClientManager.RegisterBroadcast<SwarmBarBroadcast>((Action<SwarmBarBroadcast, Channel>)OnSwarmBar);
				}
				if (_clientRegistered)
				{
					InstanceFinder.ClientManager.RegisterBroadcast<PlayerLiftBroadcast>((Action<PlayerLiftBroadcast, Channel>)OnPlayerLift);
					InstanceFinder.ClientManager.RegisterBroadcast<GunShotBroadcast>((Action<GunShotBroadcast, Channel>)OnGunShot);
				}
				if (!_serverRegistered && (Object)(object)InstanceFinder.ServerManager != (Object)null)
				{
					_serverRegistered = true;
					InstanceFinder.ServerManager.RegisterBroadcast<SeagullHandshakeBroadcast>((Action<NetworkConnection, SeagullHandshakeBroadcast, Channel>)OnHandshake, true);
				}
			}
		}

		private static void OnSwarmBar(SwarmBarBroadcast msg, Channel channel)
		{
			if (!InstanceFinder.IsServerStarted)
			{
				SwarmBar.Apply(msg);
			}
		}

		private static void OnHandshake(NetworkConnection conn, SeagullHandshakeBroadcast msg, Channel channel)
		{
			PlayerLift.MarkModded(conn, msg.Version);
		}

		private static void OnPlayerLift(PlayerLiftBroadcast msg, Channel channel)
		{
			PlayerLift.ApplyOnClient(msg);
		}

		private static void OnGunShot(GunShotBroadcast msg, Channel channel)
		{
			if (!InstanceFinder.IsServerStarted)
			{
				GunBird.PlayShotSound(msg);
			}
		}

		public static void SendGunShot(GunShotBroadcast msg)
		{
			if (!InstanceFinder.IsServerStarted || (Object)(object)InstanceFinder.ServerManager == (Object)null)
			{
				return;
			}
			try
			{
				InstanceFinder.ServerManager.Broadcast<GunShotBroadcast>(msg, true, (Channel)1);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Failed to send a seagull gun shot: " + ex.Message));
			}
		}

		public static void SendHandshake()
		{
			if (!InstanceFinder.IsClientStarted || (Object)(object)InstanceFinder.ClientManager == (Object)null)
			{
				return;
			}
			try
			{
				InstanceFinder.ClientManager.Broadcast<SeagullHandshakeBroadcast>(new SeagullHandshakeBroadcast
				{
					Version = 1
				}, (Channel)0);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to send the handshake: " + ex));
			}
		}

		public static void SendPlayerLift(PlayerLiftBroadcast msg)
		{
			if (!InstanceFinder.IsServerStarted || (Object)(object)InstanceFinder.ServerManager == (Object)null)
			{
				return;
			}
			try
			{
				InstanceFinder.ServerManager.Broadcast<PlayerLiftBroadcast>(msg, true, (Channel)0);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to send the player lift update: " + ex));
			}
		}

		public static void SendSwarmBar(SwarmBarBroadcast msg)
		{
			if (!InstanceFinder.IsServerStarted || (Object)(object)InstanceFinder.ServerManager == (Object)null)
			{
				return;
			}
			try
			{
				InstanceFinder.ServerManager.Broadcast<SwarmBarBroadcast>(msg, true, (Channel)0);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to send the swarm bar update: " + ex));
			}
		}
	}
	public static class Patches
	{
		public static void ApplyAll(Harmony harmony)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Expected O, but got Unknown
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Expected O, but got Unknown
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Expected O, but got Unknown
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Expected O, but got Unknown
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Expected O, but got Unknown
			//IL_0271: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Expected O, but got Unknown
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Expected O, but got Unknown
			MethodInfo methodInfo = AccessTools.Method(typeof(PlayerMovement), "Move", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "MovePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			else
			{
				Plugin.Log.LogWarning((object)"Could not find PlayerMovement.Move, so seagulls will not be able to carry players.");
			}
			harmony.Patch((MethodBase)AccessTools.Method(typeof(ItemManager), "AvailableItemForBird", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "AvailableItemForBirdPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Bird), "SetCaughtFood", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "SetCaughtFoodPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(BirdManager), "AddFlyingBird", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "AddFlyingBirdPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(BirdManager), "RemoveFlyingBird", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "RemoveFlyingBirdPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(BirdManager), "SimulateBird", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "SimulateBirdPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(CreatureUtils), "GetFlyDirection", new Type[1] { typeof(Bird) }, (Type[])null), new HarmonyMethod(typeof(Patches), "GetFlyDirectionPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Weapon), "ShootEffects", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "ShootEffectsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Boat), "FixedUpdate", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "BoatFixedUpdatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(BossManager), "InitializeBossFight", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "InitializeBossFightPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(BossManager), "OnPlayerCountChange", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Patches), "OnPlayerCountChangePrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			harmony.Patch((MethodBase)AccessTools.Method(typeof(Creature), "ServerChangeHp", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(Patches), "ServerChangeHpPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static bool AvailableItemForBirdPrefix(Bird bird, ref Item __result)
		{
			__result = Targeting.FindTarget(bird);
			return false;
		}

		private static bool SetCaughtFoodPrefix(Bird __instance)
		{
			return Targeting.PrepareForCatch(__instance);
		}

		private static void AddFlyingBirdPostfix(Bird bird)
		{
			Birds.Add(bird);
		}

		private static void RemoveFlyingBirdPostfix(Bird bird)
		{
			Birds.Remove(bird);
		}

		private static bool SimulateBirdPrefix(Bird bird)
		{
			if (BoatLift.IsCrew(bird))
			{
				BoatLift.SimulateCrewBird(bird);
				return false;
			}
			if (!Swarm.IsAttacking(bird))
			{
				return true;
			}
			Swarm.SimulateAttack(bird);
			return false;
		}

		private static bool GetFlyDirectionPrefix(Bird bird, ref Vector3 __result)
		{
			return HeldTargetFix.GetFlyDirection(bird, ref __result);
		}

		private static void ShootEffectsPostfix(Weapon __instance)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			if (!InstanceFinder.IsServerStarted || (Object)(object)__instance == (Object)null || (Object)(object)((Item)__instance).BirdHolder == (Object)null)
			{
				return;
			}
			Attachments attachments = __instance.Attachments;
			if (!((Object)(object)attachments == (Object)null) && !((Object)(object)attachments.FirePoint == (Object)null))
			{
				string fireSound = attachments.FireSound;
				if (!string.IsNullOrEmpty(fireSound))
				{
					AudioManager.PlayRandomClipAt(fireSound, 1, Mathf.Max(1, attachments.FireSoundCount), attachments.FirePoint.position, false, (AudioDistance)(attachments.UseMediumSoundDistance ? 2 : 3), attachments.FireSoundVolume, 0.1f);
				}
			}
		}

		private static void BoatFixedUpdatePostfix()
		{
			BoatLift.DriveBoat();
		}

		private static void InitializeBossFightPrefix()
		{
			SwarmBar.ForceHideForRealBoss();
			if (!Plugin.SwarmAllowDuringBoss.Value)
			{
				Swarm.EndForRealBoss();
			}
		}

		private static bool OnPlayerCountChangePrefix()
		{
			return !SwarmBar.Showing;
		}

		private static void ServerChangeHpPostfix(Creature __instance)
		{
			Bird val = (Bird)(object)((__instance is Bird) ? __instance : null);
			if (val != null)
			{
				Swarm.OnBirdDamaged(val);
			}
		}

		private static void MovePostfix()
		{
			PlayerLift.ApplyCarryVelocity();
		}
	}
	public static class PlayerLift
	{
		private static readonly HashSet<int> _moddedClientIds = new HashSet<int>();

		private static float _nextAllowedTime;

		private static float _nextCheckTime;

		private static Player _victim;

		private static Bird _carrier;

		private static float _endTime;

		private static bool _grabbed;

		private static float _swoopDeadline;

		private static float _carryAltitude;

		private static Vector3 _orbitCenter;

		private static float _orbitRadius;

		private static float _orbitSign = 1f;

		private static float _orbitAngle;

		private static Bird _localCarrier;

		private static Rigidbody _localRig;

		private static readonly List<Collider> _ignored = new List<Collider>();

		public static bool Active => (Object)(object)_victim != (Object)null;

		public static bool IsCarrier(Bird bird)
		{
			if ((Object)(object)bird != (Object)null)
			{
				return (Object)(object)_carrier == (Object)(object)bird;
			}
			return false;
		}

		public static void MarkModded(NetworkConnection conn, int version)
		{
			if (!(conn == (NetworkConnection)null))
			{
				if (version != 1)
				{
					Plugin.Log.LogWarning((object)$"Client {conn.ClientId} runs GreedySeagulls protocol {version}, this host is {1}. Seagulls will not carry that player.");
				}
				else if (_moddedClientIds.Add(conn.ClientId))
				{
					Plugin.Log.LogInfo((object)$"Client {conn.ClientId} has GreedySeagulls installed and can be carried off.");
				}
			}
		}

		public static void Forget(Bird bird)
		{
			if (!((Object)(object)bird == (Object)null))
			{
				if ((Object)(object)_carrier == (Object)(object)bird)
				{
					ReleaseOnServer("the seagull is gone", announce: false);
				}
				if ((Object)(object)_localCarrier == (Object)(object)bird)
				{
					ClearLocal();
				}
			}
		}

		public static void Reset()
		{
			_moddedClientIds.Clear();
			_nextAllowedTime = 0f;
			_nextCheckTime = 0f;
			ReleaseOnServer("the session ended", announce: false);
			ClearLocal();
		}

		private static bool CanBeCarried(Player player)
		{
			if ((Object)(object)player == (Object)null || (Object)(object)player.Dying == (Object)null || player.Dying.IsDead)
			{
				return false;
			}
			if ((Object)(object)player.Vitals == (Object)null || player.Vitals.Health <= 0)
			{
				return false;
			}
			if ((Object)(object)player == (Object)(object)Player.LocalPlayer)
			{
				return true;
			}
			NetworkConnection owner = ((NetworkBehaviour)player).Owner;
			if (owner != (NetworkConnection)null)
			{
				return _moddedClientIds.Contains(owner.ClientId);
			}
			return false;
		}

		private static bool HasOpenSky(Player player)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			return !Physics.Raycast(player.Transform.position + Vector3.up * 1.2f, Vector3.up, Plugin.PlayerLiftSkyCheckHeight.Value, LayerMask.op_Implicit(GameInfo.LevelLayer));
		}

		public static void ForceStart()
		{
			_nextAllowedTime = 0f;
			if (!TryBegin(forced: true))
			{
				Plugin.Log.LogWarning((object)"Could not start a player lift right now.");
			}
		}

		public static void Tick()
		{
			if (!InstanceFinder.IsServerStarted)
			{
				return;
			}
			if ((Object)(object)_victim != (Object)null)
			{
				Carry();
			}
			else
			{
				if (!Plugin.PlayerLiftEnabled.Value || Swarm.Active || BoatLift.Active || Time.time < _nextCheckTime)
				{
					return;
				}
				_nextCheckTime = Time.time + Plugin.PlayerLiftCheckInterval.Value;
				if (Time.time < _nextAllowedTime)
				{
					return;
				}
				int num = ((PlayerManager.Players == null) ? 1 : PlayerManager.Players.Count);
				float num2 = Mathf.Clamp01(Plugin.PlayerLiftChancePerPlayer.Value * (float)Mathf.Max(1, num));
				if (num2 <= 0f || Random.value > num2)
				{
					if (Plugin.LogTargeting.Value)
					{
						Plugin.Log.LogInfo((object)$"Player lift roll failed at {num2:P0}.");
					}
				}
				else
				{
					TryBegin(forced: false);
				}
			}
		}

		private static bool TryBegin(bool forced)
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			List<Player> players = PlayerManager.Players;
			if (players == null || players.Count == 0)
			{
				return false;
			}
			List<Player> list = new List<Player>();
			foreach (Player item in players)
			{
				if (CanBeCarried(item) && HasOpenSky(item))
				{
					list.Add(item);
				}
			}
			if (list.Count == 0)
			{
				if (Plugin.LogTargeting.Value || forced)
				{
					Plugin.Log.LogInfo((object)"Player lift: nobody is both under open sky and running the mod.");
				}
				return false;
			}
			Player val = list[Random.Range(0, list.Count)];
			Bird val2 = PickBird(val.Transform.position);
			if ((Object)(object)val2 == (Object)null)
			{
				if (Plugin.LogTargeting.Value || forced)
				{
					Plugin.Log.LogInfo((object)"Player lift: no seagull was available.");
				}
				return false;
			}
			_victim = val;
			_carrier = val2;
			_grabbed = false;
			_swoopDeadline = Time.time + Plugin.PlayerLiftSwoopTimeout.Value;
			_nextAllowedTime = Time.time + Plugin.PlayerLiftCooldownMinutes.Value * 60f;
			val2.SetAttackingFood((Item)null);
			string text = (string.IsNullOrEmpty(val.SteamName) ? "someone" : val.SteamName);
			Plugin.Log.LogInfo((object)("A seagull is diving at " + text + "."));
			return true;
		}

		private static Bird PickBird(Vector3 near)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			Bird result = null;
			float num = float.MaxValue;
			foreach (Bird item in Birds.All)
			{
				if (!((Object)(object)item == (Object)null) && !((Creature)item).IsDead && !((Object)(object)item.CaughtItem != (Object)null) && !BoatLift.IsCrew(item) && !Swarm.IsAttacking(item))
				{
					float num2 = Vector3.Distance(((Component)item).transform.position, near);
					if (num2 < num)
					{
						result = item;
						num = num2;
					}
				}
			}
			return result;
		}

		private static void Carry()
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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_0102: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_victim == (Object)null)
			{
				return;
			}
			if ((Object)(object)_carrier == (Object)null || ((Creature)_carrier).IsDead)
			{
				ReleaseOnServer(_grabbed ? "the seagull was shot down" : "the seagull was shot down on the way in", _grabbed);
				return;
			}
			if ((Object)(object)_victim.Dying == (Object)null || _victim.Dying.IsDead || (Object)(object)_victim.Vitals == (Object)null || _victim.Vitals.Health <= 0)
			{
				ReleaseOnServer("they died", announce: false);
				return;
			}
			if (!_grabbed)
			{
				Swoop();
				return;
			}
			if (Time.time >= _endTime)
			{
				ReleaseOnServer("the seagull got bored", announce: true);
				return;
			}
			Vector3 position = ((Component)_carrier).transform.position;
			if (position.y < _carryAltitude - 0.5f)
			{
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(position.x, _carryAltitude, position.z);
				((Component)_carrier).transform.position = Vector3.MoveTowards(position, val, Plugin.PlayerLiftBirdSpeed.Value * Time.deltaTime);
				_carrier.SetAnimState((byte)4);
				return;
			}
			_orbitAngle += _orbitSign * Plugin.PlayerLiftBirdSpeed.Value / Mathf.Max(1f, _orbitRadius) * Time.deltaTime;
			Vector3 position2 = _orbitCenter + new Vector3(Mathf.Cos(_orbitAngle), 0f, Mathf.Sin(_orbitAngle)) * _orbitRadius;
			position2.y = _carryAltitude;
			((Component)_carrier).transform.position = position2;
			Vector3 val2 = new Vector3(0f - Mathf.Sin(_orbitAngle), 0f, Mathf.Cos(_orbitAngle)) * _orbitSign;
			((Component)_carrier).transform.forward = ((Vector3)(ref val2)).normalized;
			_carrier.SetAnimState((byte)1);
		}

		private static void Swoop()
		{
			//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_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_0028: 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_0043: 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_0055: 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_0060: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = _victim.Transform.position + Vector3.up * Plugin.PlayerLiftGrabHeight.Value;
			Vector3 position = ((Component)_carrier).transform.position;
			((Component)_carrier).transform.position = Vector3.MoveTowards(position, val, Plugin.PlayerLiftSwoopSpeed.Value * Time.deltaTime);
			Vector3 val2 = val - position;
			val2.y = 0f;
			if (((Vector3)(ref val2)).sqrMagnitude > 0.01f)
			{
				((Component)_carrier).transform.forward = ((Vector3)(ref val2)).normalized;
			}
			_carrier.SetAnimState((byte)2);
			if (Vector3.Distance(((Component)_carrier).transform.position, val) <= Plugin.PlayerLiftGrabRange.Value)
			{
				BeginCarry();
			}
			else if (Time.time >= _swoopDeadline)
			{
				ReleaseOnServer("the seagull could not reach them", announce: false);
			}
		}

		private static void BeginCarry()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0053: 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_008d: 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_0098: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: 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)
			_grabbed = true;
			_endTime = Time.time + Plugin.PlayerLiftDuration.Value;
			Vector3 position = _victim.Transform.position;
			float y = position.y;
			RaycastHit val = default(RaycastHit);
			if (Physics.Raycast(position + Vector3.up * 2f, Vector3.down, ref val, 100f, LayerMask.op_Implicit(GameInfo.LevelLayer)))
			{
				y = ((RaycastHit)(ref val)).point.y;
			}
			_carryAltitude = y + Plugin.PlayerLiftHeight.Value;
			_orbitCenter = new Vector3(position.x, _carryAltitude, position.z);
			_orbitRadius = Mathf.Max(2f, Plugin.PlayerLiftOrbitRadius.Value);
			_orbitSign = ((Random.value < 0.5f) ? (-1f) : 1f);
			Vector3 val2 = ((Component)_carrier).transform.position - _orbitCenter;
			val2.y = 0f;
			_orbitAngle = ((((Vector3)(ref val2)).sqrMagnitude > 0.01f) ? Mathf.Atan2(val2.z, val2.x) : 0f);
			int clientId = ((((NetworkBehaviour)_victim).Owner != (NetworkConnection)null) ? ((NetworkBehaviour)_victim).Owner.ClientId : (-1));
			int birdObjectId = (((Object)(object)((NetworkBehaviour)_carrier).NetworkObject != (Object)null) ? ((NetworkBehaviour)_carrier).NetworkObject.ObjectId : (-1));
			Net.SendPlayerLift(new PlayerLiftBroadcast
			{
				ClientId = clientId,
				BirdObjectId = birdObjectId,
				Grabbed = true
			});
			ApplyOnClient(new PlayerLiftBroadcast
			{
				ClientId = clientId,
				BirdObjectId = birdObjectId,
				Grabbed = true
			});
			string text = (string.IsNullOrEmpty(_victim.SteamName) ? "someone" : _victim.SteamName);
			Plugin.Log.LogInfo((object)$"A seagull has grabbed {text} and is carrying them off for {Plugin.PlayerLiftDuration.Value:F0}s. Shoot the bird to get dropped.");
			if (Plugin.PlayerLiftAnnounceInChat.Value)
			{
				ChatManager.ChatMessage("<i>A seagull has picked up " + text + ".</i>");
			}
		}

		private static void ReleaseOnServer(string why, bool announce)
		{
			if (!((Object)(object)_victim == (Object)null))
			{
				Player victim = _victim;
				_victim = null;
				_carrier = null;
				_grabbed = false;
				int clientId = ((((NetworkBehaviour)victim).Owner != (NetworkConnection)null) ? ((NetworkBehaviour)victim).Owner.ClientId : (-1));
				Net.SendPlayerLift(new PlayerLiftBroadcast
				{
					ClientId = clientId,
					BirdObjectId = -1,
					Grabbed = false
				});
				ApplyOnClient(new PlayerLiftBroadcast
				{
					ClientId = clientId,
					BirdObjectId = -1,
					Grabbed = false
				});
				Plugin.Log.LogInfo((object)("Player lift ended: " + why + "."));
				if (announce && Plugin.PlayerLiftAnnounceInChat.Value)
				{
					string text = (string.IsNullOrEmpty(victim.SteamName) ? "someone" : victim.SteamName);
					ChatManager.ChatMessage("<i>" + text + " is back on the ground.</i>");
				}
			}
		}

		public static void ApplyOnClient(PlayerLiftBroadcast msg)
		{
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer == (Object)null || ((NetworkBehaviour)localPlayer).Owner == (NetworkConnection)null || ((NetworkBehaviour)localPlayer).Owner.ClientId != msg.ClientId)
			{
				return;
			}
			if (!msg.Grabbed)
			{
				ClearLocal();
				return;
			}
			Bird val = FindBird(msg.BirdObjectId);
			if (!((Object)(object)val == (Object)null))
			{
				_localCarrier = val;
				_localRig = FindRig(localPlayer);
				IgnoreCarrierCollisions(localPlayer, val, ignore: true);
				if ((Object)(object)_localRig == (Object)null)
				{
					Plugin.Log.LogWarning((object)"A seagull grabbed you but the mod could not find your rigidbody, so nothing will happen.");
				}
			}
		}

		private static Bird FindBird(int objectId)
		{
			foreach (Bird item in Birds.All)
			{
				if ((Object)(object)item != (Object)null && (Object)(object)((NetworkBehaviour)item).NetworkObject != (Object)null && ((NetworkBehaviour)item).NetworkObject.ObjectId == objectId)
				{
					return item;
				}
			}
			return null;
		}

		private static Rigidbody FindRig(Player player)
		{
			PlayerMovement movement = player.Movement;
			if ((Object)(object)movement == (Object)null)
			{
				return null;
			}
			object? obj = AccessTools.Field(typeof(PlayerMovement), "_rig")?.GetValue(movement);
			return (Rigidbody)((obj is Rigidbody) ? obj : null);
		}

		private static void ClearLocal()
		{
			RestoreCollisions();
			_localCarrier = null;
			_localRig = null;
		}

		private static void IgnoreCarrierCollisions(Player player, Bird bird, bool ignore)
		{
			RestoreCollisions();
			if (!ignore || (Object)(object)player == (Object)null || (Object)(object)bird == (Object)null)
			{
				return;
			}
			Collider[] componentsInChildren = ((Component)player).GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || val.isTrigger)
				{
					continue;
				}
				Collider[] componentsInChildren2 = ((Component)bird).GetComponentsInChildren<Collider>(true);
				foreach (Collider val2 in componentsInChildren2)
				{
					if (!((Object)(object)val2 == (Object)null) && !val2.isTrigger)
					{
						Physics.IgnoreCollision(val, val2, true);
						_ignored.Add(val);
						_ignored.Add(val2);
					}
				}
			}
		}

		private static void RestoreCollisions()
		{
			for (int i = 0; i + 1 < _ignored.Count; i += 2)
			{
				Collider val = _ignored[i];
				Collider val2 = _ignored[i + 1];
				if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null)
				{
					Physics.IgnoreCollision(val, val2, false);
				}
			}
			_ignored.Clear();
		}

		public static void ApplyCarryVelocity()
		{
			//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_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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_localCarrier == (Object)null || (Object)(object)_localRig == (Object)null)
			{
				return;
			}
			Player localPlayer = Player.LocalPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)localPlayer.Dying == (Object)null || localPlayer.Dying.IsDead || ((Creature)_localCarrier).IsDead)
			{
				ClearLocal();
				return;
			}
			Vector3 linearVelocity = (((Component)_localCarrier).transform.position - Vector3.up * Plugin.PlayerLiftHangDistance.Value - _localRig.position) * Plugin.PlayerLiftPull.Value;
			float value = Plugin.PlayerLiftMaxSpeed.Value;
			if (((Vector3)(ref linearVelocity)).sqrMagnitude > value * value)
			{
				linearVelocity = ((Vector3)(ref linearVelocity)).normalized * value;
			}
			_localRig.linearVelocity = linearVelocity;
		}
	}
	[BepInPlugin("dazed.howtofish.greedyseagulls", "GreedySeagulls", "1.3.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "dazed.howtofish.greedyseagulls";

		public const string Name = "GreedySeagulls";

		public const string Version = "1.3.1";

		public static ManualLogSource Log;

		public static ConfigEntry<bool> VaryBirdScale;

		public static ConfigEntry<float> MinBirdScale;

		public static ConfigEntry<float> MaxBirdScale;

		public static ConfigEntry<int> BirdScaleSeed;

		public static ConfigEntry<bool> ManagePopulation;

		public static ConfigEntry<int> RoamingCap;

		public static ConfigEntry<float> SpawnRate;

		public static ConfigEntry<float> SpawnInterval;

		public static ConfigEntry<float> PopulationSpawnDistanceMin;

		public static ConfigEntry<float> PopulationSpawnDistanceMax;

		public static ConfigEntry<float> SpawnCruiseHeight;

		public static ConfigEntry<bool> OwnStealChecks;

		public static ConfigEntry<float> StealCheckInterval;

		public static ConfigEntry<float> WeightFish;

		public static ConfigEntry<float> WeightCorpse;

		public static ConfigEntry<float> WeightTool;

		public static ConfigEntry<float> WeightHoldable;

		public static ConfigEntry<float> SightGraceSeconds;

		public static ConfigEntry<float> LostSightCooldown;

		public static ConfigEntry<bool> LogTargeting;

		public static ConfigEntry<bool> StealFromHands;

		public static ConfigEntry<float> HandStealChance;

		public static ConfigEntry<bool> StealFromRods;

		public static ConfigEntry<float> RodStealChance;

		public static ConfigEntry<bool> StealTools;

		public static ConfigEntry<bool> StolenGunsFire;

		public static ConfigEntry<float> GunFireIntervalMin;

		public static ConfigEntry<float> GunFireIntervalMax;

		public static ConfigEntry<float> GunSpread;

		public static ConfigEntry<bool> BurstFullAuto;

		public static ConfigEntry<string> BurstWeapons;

		public static ConfigEntry<int> BurstShotsMin;

		public static ConfigEntry<int> BurstShotsMax;

		public static ConfigEntry<float> BurstShotInterval;

		public static ConfigEntry<bool> SwarmEnabled;

		public static ConfigEntry<bool> SwarmAllowDuringBoss;

		public static ConfigEntry<bool> BoatLiftAllowDuringBoss;

		public static ConfigEntry<float> SwarmChance;

		public static ConfigEntry<float> SwarmCooldownMinutes;

		public static ConfigEntry<bool> StealHoldables;

		public static ConfigEntry<string> NeverSteal;

		public static ConfigEntry<bool> DebugHotkeys;

		public static ConfigEntry<bool> PlayerLiftEnabled;

		public static ConfigEntry<float> PlayerLiftChancePerPlayer;

		public static ConfigEntry<float> PlayerLiftCooldownMinutes;

		public static ConfigEntry<float> PlayerLiftCheckInterval;

		public static ConfigEntry<float> PlayerLiftDuration;

		public static ConfigEntry<float> PlayerLiftHeight;

		public static ConfigEntry<float> PlayerLiftHangDistance;

		public static ConfigEntry<float> PlayerLiftOrbitRadius;

		public static ConfigEntry<float> PlayerLiftSwoopSpeed;

		public static ConfigEntry<float> PlayerLiftSwoopTimeout;

		public static ConfigEntry<float> PlayerLiftGrabHeight;

		public static ConfigEntry<float> PlayerLiftGrabRange;

		public static ConfigEntry<float> PlayerLiftBirdSpeed;

		public static ConfigEntry<float> PlayerLiftPull;

		public static ConfigEntry<float> PlayerLiftMaxSpeed;

		public static ConfigEntry<float> PlayerLiftSkyCheckHeight;

		public static ConfigEntry<bool> PlayerLiftAnnounceInChat;

		public static ConfigEntry<bool> RequireOpenSkyForHandSteal;

		public static ConfigEntry<int> SwarmExtraBirds;

		public static ConfigEntry<int> SwarmBirdsPerPlayer;

		public static ConfigEntry<int> SwarmMaxExtraBirds;

		public static ConfigEntry<float> SwarmSpawnDistanceMin;

		public static ConfigEntry<float> SwarmSpawnDistanceMax;

		public static ConfigEntry<float> SwarmSpawnHeightJitter;

		public static ConfigEntry<float> SwarmApproachSpeed;

		public static ConfigEntry<float> SwarmDiveDelayMin;

		public static ConfigEntry<float> SwarmDiveDelayMax;

		public static ConfigEntry<float> SwarmCircleRadiusMin;

		public static ConfigEntry<float> SwarmCircleRadiusMax;

		public static ConfigEntry<float> SwarmDuration;

		public static ConfigEntry<int> SwarmDamage;

		public static ConfigEntry<float> SwarmHitRange;

		public static ConfigEntry<float> SwarmHitCooldown;

		public static ConfigEntry<float> SwarmKnockback;

		public static ConfigEntry<float> SwarmDiveSpeed;

		public static ConfigEntry<float> SwarmClimbSpeed;

		public static ConfigEntry<float> SwarmTurnSpeed;

		public static ConfigEntry<float> SwarmAcceleration;

		public static ConfigEntry<bool> SwarmRequireLineOfSight;

		public static ConfigEntry<float> SwarmBlockedRetry;

		public static ConfigEntry<float> SwarmGroundClearance;

		public static ConfigEntry<bool> SwarmDespawnReinforcements;

		public static ConfigEntry<bool> SwarmAnnounceInChat;

		public static ConfigEntry<bool> SwarmBossBar;

		public static ConfigEntry<string> SwarmBossBarName;

		public static ConfigEntry<float> SwarmBarSendInterval;

		public static ConfigEntry<float> SwarmBarFailsafeGrace;

		public static ConfigEntry<bool> BoatLiftEnabled;

		public static ConfigEntry<int> BoatLiftRequiredBirds;

		public static ConfigEntry<float> BoatLiftChancePerPlayer;

		public static ConfigEntry<int> BoatLiftSpawnedBirds;

		public static ConfigEntry<float> BoatLiftSpawnDistanceMin;

		public static ConfigEntry<float> BoatLiftSpawnDistanceMax;

		public static ConfigEntry<bool> BoatLiftDespawnHelpers;

		public static ConfigEntry<float> BoatLiftCheckInterval;

		public static ConfigEntry<float> BoatLiftCooldownMinutes;

		public static ConfigEntry<float> BoatLiftGatherTimeout;

		public static ConfigEntry<float> BoatLiftDuration;

		public static ConfigEntry<float> BoatLiftRadiusX;

		public static ConfigEntry<float> BoatLiftRadiusZ;

		public static ConfigEntry<float> BoatLiftGripHeight;

		public static ConfigEntry<float> BoatLiftGripDistance;

		public static ConfigEntry<float> BoatLiftApproachSpeed;

		public static ConfigEntry<float> BoatLiftHoldSpeed;

		public static ConfigEntry<float> BoatLiftHeight;

		public static ConfigEntry<float> BoatLiftRiseSpeed;

		public static ConfigEntry<float> BoatLiftCruiseSpeed;

		public static ConfigEntry<float> BoatLiftLevelStrength;

		public static ConfigEntry<float> BoatLiftMaxLevelSpeed;

		public static ConfigEntry<float> BoatLiftOrbitRadiusMin;

		public static ConfigEntry<float> BoatLiftOrbitRadiusMax;

		public static ConfigEntry<float> BoatLiftOrbitCorrection;

		private Harmony _harmony;

		private static bool _handshakeSent;

		private void Awake()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			if (!Refl.Resolve())
			{
				Log.LogError((object)"Aborting: the game does not look the way this mod expects.");
				return;
			}
			Net.RegisterSerializers();
			Exclusions.Rebuild();
			_harmony = new Harmony("dazed.howtofish.greedyseagulls");
			Patches.ApplyAll(_harmony);
			Server.OnServerStopped += OnServerStopped;
			Log.LogInfo((object)"GreedySeagulls 1.3.1 loaded. The host drives everything, but every player should have it installed.");
		}

		private void BindConfig()
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Expected O, but got Unknown
			VaryBirdScale = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance", "VaryScale", true, "Give each seagull its own size, so the flock is not made of identical birds.");
			MinBirdScale = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "MinScale", 1f, "Smallest size multiplier. 1 is the normal seagull size.");
			MaxBirdScale = ((BaseUnityPlugin)this).Config.Bind<float>("Appearance", "MaxScale", 1.5f, "Largest size multiplier.");
			BirdScaleSeed = ((BaseUnityPlugin)this).Config.Bind<int>("Appearance", "ScaleSeed", 0, "Mixed into each seagull's size roll. Every player using the same seed sees the same birds at the same sizes. Change it if you want a different set of sizes.");
			ManagePopulation = ((BaseUnityPlugin)this).Config.Bind<bool>("Population", "ManagePopulation", true, "Keep a steady number of seagulls flying around, topping the flock back up as birds are killed or fly off. Turn this off to leave the seagull count entirely to the game.");
			RoamingCap = ((BaseUnityPlugin)this).Config.Bind<int>("Population", "RoamingCap", 3, new ConfigDescription("How many ordinary seagulls may be in the air at once. 3 is close to what the game gives you. Raising this makes the island noticeably busier, and every extra bird is another one that can steal from you. The swarm event ignores this cap completely, so its reinforcements still arrive in full.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 20), Array.Empty<object>()));
			SpawnRate = ((BaseUnityPlugin)this).Config.Bind<float>("Population", "SpawnRate", 1f, new ConfigDescription("How quickly the flock is topped back up toward the cap. 1 is the normal pace. 10 replaces losses ten times as fast, so shooting seagulls barely thins them out.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
			SpawnInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Population", "SpawnInterval", 30f, "Seconds between population checks at a SpawnRate of 1. One seagull is added per check while the flock is under the cap, so this is the pace that SpawnRate multiplies.");
			PopulationSpawnDistanceMin = ((BaseUnityPlugin)this).Config.Bind<float>("Population", "SpawnDistanceMin", 45f, "Closest a replacement seagull can appear from a player. Far enough that they fly in rather than popping into view.");
			PopulationSpawnDistanceMax = ((BaseUnityPlugin)this).Config.Bind<float>("Population", "SpawnDistanceMax", 80f, "Furthest a replacement seagull can appear from a player.");
			SpawnCruiseHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Population", "SpawnCruiseHeight", 20f, "Metres above the ground a seagull is placed when this mod spawns one and there is no living seagull left to copy an altitude from. Every spawn is measured from the ground beneath it, so this only decides how high the first bird of a wiped out flock comes back.");
			OwnStealChecks = ((BaseUnityPlugin)this).Config.Bind<bool>("Stealing", "OwnStealChecks", true, "Run our own target check on a timer instead of relying on the game's. The game only considers one seagull every thousand ticks, roughly half a minute, which makes stealing almost never happen. Turn this off to fall back to vanilla timing.");
			StealCheckInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Stealing", "CheckInterval", 12f, "Seconds between target checks when OwnStealChecks is on. Each check picks one idle seagull.");
			WeightFish = ((BaseUnityPlugin)this).Config.Bind<float>("Stealing", "WeightFish", 1f, "How attractive a loose fish is. Targets are chosen by distance divided by weight, so a higher weight makes something worth flying further for.");
			WeightCorpse = ((BaseUnityPlugin)this).Config.Bind<float>("Stealing", "WeightCorpse", 1f, "How attractive a downed player is.");
			WeightTool = ((BaseUnityPlugin)this).Config.Bind<float>("Stealing", "WeightTool", 2.5f, "How attractive a tool or weapon is. Above 1 so a gun can win against a closer fish, otherwise the new targets almost never get picked.");
			WeightHoldable = ((BaseUnityPlugin)this).Config.Bind<float>("Stealing", "WeightHoldable", 2.5f, "How attractive anything else holdable is, such as a radio.");
			SightGraceSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Stealing", "SightGraceSeconds", 1.5f, "How long a seagull keeps diving after losing sight of its target before giving up. A short grace stops it aborting over a wave or a passing prop, while still cancelling when someone ducks into a building.");
			LostSightCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Stealing", "LostSightCooldown", 20f, "Seconds a seagull waits before picking a new target after being given the slip, so it does not immediately dive at the same doorway again.");
			LogTargeting = ((BaseUnityPlugin)this).Config.Bind<bool>("Stealing", "LogTargeting", false, "Log every target scan with the reason each item was rejected. Use this to find out why seagulls are ignoring something.");
			StealFromHands = ((BaseUnityPlugin)this).Config.Bind<bool>("Stealing", "StealFromHands", true, "Seagulls can snatch whatever a player is currently holding.");
			HandStealChance = ((BaseUnityPlugin)this).Config.Bind<float>("Stealing", "HandStealChance", 0.35f, "Chance from 0 to 1 that a held item is considered when a seagull picks a target. Seagulls only pick targets occasionally, so this is not a per second chance.");
			StealFromRods = ((BaseUnityPlugin)this).Config.Bind<bool>("Stealing", "StealFromRods", true, "Seagulls can snatch a fish hooked on a fishing rod once it is out of the water.");
			RodStealChance = ((BaseUnityPlugin)this).Config.Bind<float>("Stealing", "RodStealChance", 0.6f, "Chance from 0 to 1 that a hooked fish is considered when a seagull picks a target.");
			StealTools = ((BaseUnityPlugin)this).Config.Bind<bool>("Stealing", "StealTools", true, "Seagulls can steal tools and weapons, not just fish.");
			StealHoldables = ((BaseUnityPlugin)this).Config.Bind<bool>("Stealing", "StealHoldables", true, "Seagulls can steal anything else a player can pick up, such as radios.");
			NeverSteal = ((BaseUnityPlugin)this).Config.Bind<string>("Stealing", "NeverSteal", "Clam,FootSnail,Leech", "Comma separated list of things seagulls will never take. Entries match the prefab name, which does not change with language, or the display name, or a numeric item id. Spaces and underscores are ignored, and matching is case insensitive.");
			DebugHotkeys = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugHotkeys", false, "Host only. F6 forces a player lift, F7 forces a boat lift, F8 forces a swarm. For testing events without waiting on the cooldown.");
			PlayerLiftEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Player Lift", "Enabled", true, "A seagull can pick a player up and fly off with them. The player keeps full control of aiming and shooting, so looking up and shooting the bird gets them dropped. Every player needs the mod for this, and the host will only carry players it has confirmed are running it.");
			PlayerLiftChancePerPlayer = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "ChancePerPlayer", 0.05f, "Chance per player that a lift is attempted when one is due. With four players that is 20 percent.");
			PlayerLiftCooldownMinutes = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "CooldownMinutes", 30f, "Minutes after a lift before another can be attempted.");
			PlayerLiftCheckInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "CheckInterval", 20f, "Seconds between rolls once the cooldown has passed.");
			PlayerLiftDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "Duration", 25f, "Seconds a seagull carries a player before losing interest.");
			PlayerLiftHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "Height", 14f, "Metres above the player the carrying seagull flies.");
			PlayerLiftHangDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "HangDistance", 2f, "Metres below the seagull the carried player hangs.");
			PlayerLiftSwoopSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "SwoopSpeed", 16f, "How fast the seagull dives in to grab the player. Higher feels like a strike, lower gives more time to shoot it on the way in.");
			PlayerLiftSwoopTimeout = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "SwoopTimeout", 8f, "Seconds the seagull gets to reach the player before giving up. Stops a bird stuck behind geometry circling forever.");
			PlayerLiftGrabHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "GrabHeight", 1.9f, "Metres above the player's feet the seagull aims for, so it grabs at head height rather than the floor.");
			PlayerLiftGrabRange = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "GrabRange", 1.5f, "How close the seagull must get before the grab takes hold.");
			PlayerLiftOrbitRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "OrbitRadius", 12f, "Metres the seagull circles around the spot it grabbed the player from. The circuit is flown at a fixed height so the pair cannot climb each other.");
			PlayerLiftBirdSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "BirdSpeed", 6f, "How fast the carrying seagull moves.");
			PlayerLiftPull = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "Pull", 6f, "How hard the player is pulled towards the seagull. Higher is a stiffer, less swingy carry.");
			PlayerLiftMaxSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "MaxSpeed", 18f, "Fastest the carried player can be moved, so a long grab does not fling them.");
			PlayerLiftSkyCheckHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Player Lift", "SkyCheckHeight", 12f, "Metres of clear sky a player needs above them before a seagull will try. Stops grabs through roofs and inside buildings.");
			PlayerLiftAnnounceInChat = ((BaseUnityPlugin)this).Config.Bind<bool>("Player Lift", "AnnounceInChat", true, "Announce in chat when a player is picked up and put down.");
			if (string.Equals(NeverSteal.Value.Trim(), "Clam", StringComparison.OrdinalIgnoreCase))
			{
				NeverSteal.Value = "Clam,FootSnail";
				Log.LogInfo((object)"Added FootSnail to NeverSteal. Seagulls on the lava map spent the whole time carrying snails instead of going after anything else.");
			}
			if (string.Equals(NeverSteal.Value.Trim(), "Clam,FootSnail", StringComparison.OrdinalIgnoreCase))
			{
				NeverSteal.Value = "Clam,FootSnail,Leech";
				Log.LogInfo((object)"Added Leech to NeverSteal.");
			}
			RequireOpenSkyForHandSteal = ((BaseUnityPlugin)this).Config.Bind<bool>("Stealing", "RequireOpenSkyForHandSteal", true, "A seagull will only dive for a held item if there is open sky above it. Turn this off if you want them to snatch things from under roofs and canopies.");
			StolenGunsFire = ((BaseUnityPlugin)this).Config.Bind<bool>("Stolen Guns", "StolenGunsFire", true, "A seagull carrying a gun fires it in whatever direction the barrel happens to be pointing.");
			GunFireIntervalMin = ((BaseUnityPlugin)this).Config.Bind<float>("Stolen Guns", "FireIntervalMin", 0.8f, "Shortest gap in seconds between shots from a stolen gun.");
			GunFireIntervalMax = ((BaseUnityPlugin)this).Config.Bind<float>("Stolen Guns", "FireIntervalMax", 3.5f, "Longest gap in seconds between shots from a stolen gun.");
			BurstFullAuto = ((BaseUnityPlugin)this).Config.Bind<bool>("Stolen Guns", "BurstFullAuto", true, "Full automatic guns such as the SMG are fired in short bursts rather than single shots. This reads the game's own full auto flag, so it needs n