Decompiled source of FurstMate v0.9.6

FurstMate.dll

Decompiled 15 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using Crest;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FurstMate
{
	internal enum PerchKind
	{
		Truck,
		Bow,
		Yard,
		Low,
		Near,
		Deck
	}
	internal class BirdPerch
	{
		internal PerchKind Kind;

		internal Transform Parent;

		internal Vector3 Local;

		internal Vector3 Fwd;

		internal Vector3 Up;

		internal string Name;

		internal bool Ok
		{
			get
			{
				if ((Object)(object)Parent != (Object)null)
				{
					return ((Component)Parent).gameObject.activeInHierarchy;
				}
				return false;
			}
		}

		internal Vector3 World => Parent.TransformPoint(Local);

		internal Quaternion LocalTurn => Quaternion.LookRotation(Fwd, Up);

		internal Quaternion Turn => Parent.rotation * LocalTurn;

		internal bool WithinReach
		{
			get
			{
				if (Kind != PerchKind.Near)
				{
					return Kind == PerchKind.Deck;
				}
				return true;
			}
		}

		internal bool Steep
		{
			get
			{
				if (Kind != PerchKind.Near && Kind != PerchKind.Deck)
				{
					return Kind == PerchKind.Low;
				}
				return true;
			}
		}
	}
	internal abstract class BirdWorld
	{
		internal abstract Transform FlightParent { get; }

		internal abstract Vector3 BoatPos { get; }

		internal abstract Vector3 BoatBow { get; }

		internal abstract Vector3 BoatVelocity { get; }

		internal abstract float HalfBeam { get; }

		internal abstract bool PlayerAboard { get; }

		internal abstract Vector3 PlayerFeet { get; }

		internal abstract float LookDownWithin { get; }

		internal abstract bool LandNear { get; }

		internal abstract bool HiddenLand { get; }

		internal abstract Vector3 LandBearing { get; }

		internal abstract bool Severe { get; }

		internal abstract bool Night { get; }

		internal abstract List<BirdPerch> Perches { get; }

		internal abstract Vector3 HoverSpot { get; }

		internal abstract Vector3 DeckSpot { get; }

		internal abstract bool StayAwake { get; }

		internal abstract bool Begging { get; }

		internal abstract void PickDeckSpot();

		internal abstract float SeaY(Vector3 p);

		internal abstract void Play(string sound);

		internal abstract void Splash(Vector3 at);

		internal abstract GameObject FishLook();

		internal abstract void DropFish(Vector3 at);

		internal abstract void Note(string s);

		internal abstract void Snacked();

		internal virtual void Remove(GameObject g)
		{
			Object.Destroy((Object)(object)g);
		}
	}
	internal class BirdFlight
	{
		private enum Mode
		{
			Perched,
			Springing,
			Climbing,
			ToLand,
			Landing,
			ToHover,
			Hovering,
			ToDive,
			Diving,
			Under,
			Carrying,
			Dropping,
			Circling,
			Away,
			Gone
		}

		private enum Then
		{
			Perch,
			Hover,
			Fish,
			Snack,
			Leave
		}

		private class Body
		{
			internal GameObject go;

			internal Animator anim;

			internal SkinnedMeshRenderer smr;

			internal Transform chest;

			internal Transform jaw;

			internal Vector3 tip;

			internal bool hasTip;
		}

		private class Due
		{
			internal float at;

			internal string name;
		}

		private const int Idle = 0;

		private const int Look = 1;

		private const int Preen = 2;

		private const int Sleep = 3;

		private const int Pace = 4;

		private const int Call = 5;

		private const int Hunker = 6;

		private const int Spring = 7;

		private const int Eat = 8;

		private const int Alarm = 9;

		private const int Brown = 10;

		private const int Glide = 0;

		private const int Flap = 1;

		private const int Hover = 2;

		private const int Dive = 3;

		private const int HoverDown = 4;

		private const int HoverCry = 5;

		private const int HoverDownCry = 6;

		private const int NoState = 9;

		private const float CallStart = 0.517f;

		private const float AlarmStart = 0.317f;

		private const float BrownStart = 0.25f;

		private const float CryStart = 0.25f;

		private const float LandT = 1.6f;

		private const float LandV = 7f;

		private const float LandD = 0.6f;

		internal readonly Transform Root;

		private readonly BirdWorld W;

		private readonly Body _p;

		private readonly Body _f;

		private Body _cur;

		private readonly float _size;

		private readonly Vector3 _pSettle;

		private readonly Vector3 _fLand;

		private readonly Vector3 _fTake;

		private Mode _mode = Mode.Gone;

		private Then _then;

		private BirdPerch _perch;

		private BirdPerch _landOn;

		private float _now;

		private float _t;

		private float _yaw;

		private float _pitch;

		private float _bank;

		private float _wingAt;

		private float _landLeft;

		private float _since;

		private float _holdUntil;

		private float _relocAt;

		private float _clearFor;

		private float _ang;

		private float _swept;

		private float _timeout;

		private Vector3 _vel;

		private Vector3 _landOff;

		private Vector3 _awayDir;

		private int _landStage;

		private int _state = -1;

		private bool _leave;

		private bool _fish;

		private bool _snack;

		private bool _carryFish;

		private bool _turning;

		private bool _eatNext;

		private bool _crying;

		private bool _cryIn;

		private bool _underNow;

		private BirdPerch _want;

		private float _begAt;

		private float _takeF;

		private float _landF;

		private string _once;

		private string _onceSound;

		private float _onceStart;

		private bool _onceIn;

		private int _quiet;

		private float _lastFrac;

		private int _lastClip;

		private GameObject _carry;

		private readonly List<Due> _due = new List<Due>();

		private float _sideSign = 1f;

		internal bool IsGone => _mode == Mode.Gone;

		internal bool IsPerched => _mode == Mode.Perched;

		internal bool Flying
		{
			get
			{
				if (_mode != Mode.Perched)
				{
					return _mode != Mode.Gone;
				}
				return false;
			}
		}

		internal BirdPerch PerchNow => _perch;

		internal string Doing => _mode.ToString();

		internal Animator PerchAnim => _p.anim;

		internal Animator FlyAnim => _f.anim;

		internal SkinnedMeshRenderer Skin => _cur.smr;

		internal GameObject PerchBody => _p.go;

		internal BirdFlight(GameObject perchPrefab, GameObject flyPrefab, BirdWorld world, float size)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: 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_00bd: 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)
			W = world;
			_size = size;
			Root = new GameObject("FurstMate booby").transform;
			Root.SetParent(W.FlightParent, true);
			_p = Make(perchPrefab, "Booby on her perch");
			_f = Make(flyPrefab, "Booby in the air");
			_pSettle = ChestAt(_p, "Settle", 0f);
			_fLand = ChestAt(_f, "Land", 1f);
			_fTake = ChestAt(_f, "TakeOff", 0f);
			FindTip(_f);
			_p.go.SetActive(false);
			_f.go.SetActive(false);
			_relocAt = Random.Range(900f, 2400f);
		}

		private Body Make(GameObject prefab, string name)
		{
			//IL_001b: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(prefab, Root, false);
			((Object)val).name = name;
			val.transform.localPosition = Vector3.zero;
			val.transform.localRotation = Quaternion.identity;
			val.transform.localScale = Vector3.one;
			Body body = new Body
			{
				go = val,
				anim = val.GetComponentInChildren<Animator>(true),
				smr = val.GetComponentInChildren<SkinnedMeshRenderer>(true)
			};
			body.anim.applyRootMotion = false;
			body.anim.cullingMode = (AnimatorCullingMode)0;
			Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren)
			{
				if (((Object)val2).name == "chest")
				{
					body.chest = val2;
				}
				else if (((Object)val2).name == "jaw")
				{
					body.jaw = val2;
				}
			}
			return body;
		}

		private Vector3 ChestAt(Body b, string state, float norm)
		{
			//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)
			b.anim.Rebind();
			b.anim.Play(state, 0, norm);
			b.anim.Update(0f);
			return b.go.transform.InverseTransformPoint(b.chest.position);
		}

		private void Show(Body b)
		{
			_cur = b;
			_state = -1;
			_lastClip = 0;
			_p.go.SetActive(b == _p);
			_f.go.SetActive(b == _f);
		}

		private void Hang(Transform parent)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_003a: 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)
			Root.SetParent(parent, true);
			Vector3 lossyScale = parent.lossyScale;
			Root.localScale = new Vector3(_size / lossyScale.x, _size / lossyScale.y, _size / lossyScale.z);
		}

		private void SetState(int s)
		{
			if (s != _state)
			{
				_state = s;
				_cur.anim.SetInteger("State", s);
			}
		}

		private bool Entered(string s)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			Animator anim = _cur.anim;
			AnimatorStateInfo val = anim.GetCurrentAnimatorStateInfo(0);
			if (!((AnimatorStateInfo)(ref val)).IsName(s))
			{
				if (anim.IsInTransition(0))
				{
					val = anim.GetNextAnimatorStateInfo(0);
					return ((AnimatorStateInfo)(ref val)).IsName(s);
				}
				return false;
			}
			return true;
		}

		private bool In(string s)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			Animator anim = _cur.anim;
			if (!anim.IsInTransition(0))
			{
				AnimatorStateInfo currentAnimatorStateInfo = anim.GetCurrentAnimatorStateInfo(0);
				return ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName(s);
			}
			return false;
		}

		private void Sound(string name, float delay = 0f)
		{
			if (delay <= 0f)
			{
				W.Play(name);
				return;
			}
			_due.Add(new Due
			{
				at = _now + delay,
				name = name
			});
		}

		internal void Arrive(BirdPerch to = null)
		{
			//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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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_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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_007c: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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)
			Hang(W.FlightParent);
			Show(_f);
			Vector3 boatBow = W.BoatBow;
			Vector3 val = Vector3.Cross(Vector3.up, boatBow);
			Vector3 val2 = W.BoatPos - boatBow * 170f + val * ((Random.value < 0.5f) ? 70f : (-70f));
			val2.y = W.SeaY(val2) + 38f;
			Root.position = val2;
			_yaw = Mathf.Atan2(boatBow.x, boatBow.z) * 57.29578f;
			_vel = boatBow * 8f;
			_f.anim.Rebind();
			_f.anim.Play("Glide", 0, 0f);
			_f.anim.Update(0f);
			SetState(0);
			_landOn = ((to != null) ? to : PickHigh());
			_landStage = 0;
			_mode = Mode.ToLand;
			_wingAt = _now + 2f;
			W.Note("the booby comes in from astern, for the " + ((_landOn != null) ? _landOn.Name : "nothing") + ".");
		}

		internal void PlaceOn(BirdPerch p)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (p != null)
			{
				_perch = p;
				Show(_p);
				Hang(p.Parent);
				Root.localPosition = p.Local;
				Root.localRotation = p.LocalTurn;
				_p.anim.Rebind();
				SetState(0);
				_p.anim.Update(0f);
				_since = 0f;
				_holdUntil = _now + 8f;
				_mode = Mode.Perched;
			}
		}

		internal void Leave()
		{
			_leave = true;
		}

		internal void GoFish()
		{
			_fish = true;
		}

		internal void GoSnack()
		{
			_snack = true;
		}

		internal void GoTo(BirdPerch p)
		{
			_want = p;
		}

		internal void Fed()
		{
			_eatNext = true;
		}

		internal void Beg()
		{
			if (_mode == Mode.Perched && _once == null)
			{
				StartOnce(10, "Brown", "bird_brown", 0.25f);
				_begAt = _now + 20f;
			}
		}

		internal void Tick(float dt)
		{
			if (dt <= 0f || _mode == Mode.Gone || _cur == null)
			{
				return;
			}
			_now += dt;
			for (int num = _due.Count - 1; num >= 0; num--)
			{
				if (_now >= _due[num].at)
				{
					W.Play(_due[num].name);
					_due.RemoveAt(num);
				}
			}
			switch (_mode)
			{
			case Mode.Perched:
				PerchedTick(dt);
				break;
			case Mode.Springing:
				SpringingTick(dt);
				break;
			case Mode.Climbing:
				ClimbingTick(dt);
				break;
			case Mode.ToLand:
				ToLandTick(dt);
				break;
			case Mode.Landing:
				LandingTick(dt);
				break;
			case Mode.ToHover:
				ToHoverTick(dt);
				break;
			case Mode.Hovering:
				HoveringTick(dt);
				break;
			case Mode.ToDive:
				ToDiveTick(dt);
				break;
			case Mode.Diving:
				DivingTick(dt);
				break;
			case Mode.Under:
				UnderTick(dt);
				break;
			case Mode.Carrying:
				CarryingTick(dt);
				break;
			case Mode.Dropping:
				DroppingTick(dt);
				break;
			case Mode.Circling:
				CirclingTick(dt);
				break;
			case Mode.Away:
				AwayTick(dt);
				break;
			}
			if (_cur == _f && _f.go.activeSelf)
			{
				Beats();
			}
		}

		internal void Destroy()
		{
			if ((Object)(object)_carry != (Object)null)
			{
				W.Remove(_carry);
			}
			if ((Object)(object)Root != (Object)null)
			{
				W.Remove(((Component)Root).gameObject);
			}
		}

		private void Beats()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			AnimatorStateInfo currentAnimatorStateInfo = _f.anim.GetCurrentAnimatorStateInfo(0);
			if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("TakeOff"))
			{
				float num = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime * 42f;
				if ((_takeF < 6f && num >= 6f) || (_takeF < 18f && num >= 18f) || (_takeF < 30f && num >= 30f))
				{
					W.Play("beat");
				}
				_takeF = num;
			}
			else
			{
				_takeF = 0f;
			}
			if (((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Land"))
			{
				float num2 = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime * 48f;
				if ((_landF < 18f && num2 >= 18f) || (_landF < 29f && num2 >= 29f))
				{
					W.Play("beat");
				}
				_landF = num2;
			}
			else
			{
				_landF = 0f;
			}
			int num3 = ((((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Flap") || ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Hover")) ? 1 : ((((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("HoverDown") || ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("HoverCry") || ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("HoverDownCry")) ? 6 : 0));
			if (num3 == 0)
			{
				_lastClip = 0;
				return;
			}
			float num4 = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime * (float)num3;
			num4 -= Mathf.Floor(num4);
			if (_lastClip != ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).shortNameHash || num4 < _lastFrac)
			{
				W.Play("beat");
			}
			_lastClip = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).shortNameHash;
			_lastFrac = num4;
		}

		private BirdPerch Find(PerchKind k)
		{
			BirdPerch result = null;
			int num = 0;
			foreach (BirdPerch perch in W.Perches)
			{
				if (perch.Kind == k && perch.Ok)
				{
					num++;
					if (Random.Range(0, num) == 0)
					{
						result = perch;
					}
				}
			}
			return result;
		}

		private BirdPerch PickHigh()
		{
			List<BirdPerch> list = new List<BirdPerch>();
			foreach (BirdPerch perch in W.Perches)
			{
				if (perch.Ok && (perch.Kind == PerchKind.Truck || perch.Kind == PerchKind.Bow || perch.Kind == PerchKind.Yard))
				{
					list.Add(perch);
				}
			}
			if (list.Count == 0)
			{
				foreach (BirdPerch perch2 in W.Perches)
				{
					if (perch2.Ok)
					{
						list.Add(perch2);
					}
				}
			}
			if (list.Count <= 0)
			{
				return null;
			}
			return list[Random.Range(0, list.Count)];
		}

		private void PerchedTick(float dt)
		{
			_since += dt;
			if (_perch == null || !_perch.Ok)
			{
				_leave = true;
			}
			if (_leave)
			{
				StartSpring(Then.Leave, null);
				return;
			}
			if (_want != null && _once == null)
			{
				BirdPerch want = _want;
				_want = null;
				if (want != _perch && want.Ok)
				{
					StartSpring(Then.Perch, want);
					return;
				}
			}
			if (W.HiddenLand && !W.Severe && _since > 6f)
			{
				StartSpring(Then.Hover, null);
				return;
			}
			bool flag = !W.LandNear && !W.Severe;
			BirdPerch birdPerch = null;
			PerchKind kind = _perch.Kind;
			if (_once == null)
			{
				if (W.Severe && kind != PerchKind.Low)
				{
					birdPerch = Find(PerchKind.Low);
				}
				else if (W.LandNear && !W.Severe && kind != PerchKind.Bow && _since > 12f)
				{
					birdPerch = Find(PerchKind.Bow);
				}
				else if (!W.Severe && kind == PerchKind.Low && _since > 15f)
				{
					birdPerch = PickHigh();
				}
				else if (flag && _now >= _relocAt)
				{
					_relocAt = _now + Random.Range(900f, 2400f);
					birdPerch = PickHigh();
				}
				if (birdPerch != null && birdPerch != _perch)
				{
					StartSpring(Then.Perch, birdPerch);
					return;
				}
				if (_fish && !W.Severe)
				{
					_fish = false;
					StartSpring(Then.Fish, null);
					return;
				}
				if (_snack && !W.Severe)
				{
					_snack = false;
					StartSpring(Then.Snack, null);
					return;
				}
				if (_eatNext)
				{
					_eatNext = false;
					StartOnce(8, "Eat", null, 0f);
					return;
				}
			}
			if (_once != null)
			{
				OnceTick();
				return;
			}
			FaceYou(dt);
			if (W.Begging && _now >= _begAt)
			{
				_begAt = _now + Random.Range(20f, 35f);
				StartOnce(10, "Brown", "bird_brown", 0.25f);
			}
			else if (W.Severe)
			{
				SetState(6);
			}
			else if (W.LandNear)
			{
				LandNearTick();
			}
			else
			{
				QuietTick();
			}
		}

		private void QuietTick()
		{
			if (!(_now < _holdUntil))
			{
				float value = Random.value;
				float num = (W.StayAwake ? 0f : (W.Night ? 0.85f : 0.4f));
				if (value < num)
				{
					SetState(3);
					_holdUntil = _now + Random.Range(60f, 200f);
				}
				else if (value < num + (1f - num) * 0.4f)
				{
					SetState(0);
					_holdUntil = _now + Random.Range(15f, 40f);
				}
				else if (value < num + (1f - num) * 0.75f)
				{
					SetState(1);
					_holdUntil = _now + Random.Range(6f, 14f);
				}
				else
				{
					StartOnce(2, "Preen", null, 0f);
					_holdUntil = _now + 6f;
				}
			}
		}

		private void LandNearTick()
		{
			if (_now < _holdUntil)
			{
				return;
			}
			_quiet++;
			if (_quiet % 2 == 1)
			{
				SetState(4);
				_holdUntil = _now + Random.Range(7f, 14f);
				return;
			}
			if (Random.value < 0.6f)
			{
				StartOnce(5, "Call", "bird_call", 0.517f);
			}
			else
			{
				StartOnce(10, "Brown", "bird_brown", 0.25f);
			}
			_holdUntil = _now + Random.Range(2f, 5f);
		}

		private void FaceYou(float dt)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (_perch == null || !_perch.WithinReach || !W.PlayerAboard)
			{
				return;
			}
			Vector3 up = Root.up;
			Vector3 val = W.PlayerFeet - Root.position;
			val -= up * Vector3.Dot(val, up);
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.4f || magnitude > 7f)
			{
				_turning = false;
				return;
			}
			float num = Vector3.SignedAngle(Root.forward, val, up);
			if (!_turning && Mathf.Abs(num) > 30f)
			{
				_turning = true;
			}
			if (_turning)
			{
				Root.Rotate(up, Mathf.Clamp(num, -80f * dt, 80f * dt), (Space)0);
				if (Mathf.Abs(num) < 5f)
				{
					_turning = false;
				}
			}
		}

		private void StartOnce(int state, string name, string sound, float delay)
		{
			_once = name;
			_onceSound = sound;
			_onceStart = delay;
			_onceIn = false;
			_timeout = _now + 15f;
			SetState(state);
		}

		private void OnceTick()
		{
			if (_now > _timeout)
			{
				_once = null;
				SetState(0);
			}
			else if (!_onceIn)
			{
				if (Entered(_once))
				{
					_onceIn = true;
					if (_onceSound != null)
					{
						Sound(_onceSound, _onceStart);
					}
					SetState(0);
				}
			}
			else if (In("Idle"))
			{
				_once = null;
			}
		}

		private void StartSpring(Then then, BirdPerch to)
		{
			_then = then;
			_landOn = to;
			_mode = Mode.Springing;
			_once = null;
			_timeout = _now + 6f;
			SetState(7);
		}

		private void SpringingTick(float dt)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			AnimatorStateInfo currentAnimatorStateInfo = _p.anim.GetCurrentAnimatorStateInfo(0);
			if ((((AnimatorStateInfo)(ref currentAnimatorStateInfo)).IsName("Spring") && !_p.anim.IsInTransition(0) && ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime >= 1f) || _now > _timeout)
			{
				OffThePerch();
			}
		}

		private void OffThePerch()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00b2: 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)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ((_perch != null) ? Flat(Root.forward) : W.BoatBow);
			_yaw = Mathf.Atan2(val.x, val.z) * 57.29578f;
			_pitch = 0f;
			_bank = 0f;
			Vector3 position = _p.chest.position;
			Quaternion val2 = Quaternion.Euler(0f, _yaw, 0f);
			Hang(W.FlightParent);
			Show(_f);
			Root.rotation = val2;
			Root.position = position - val2 * (_fTake * _size);
			_f.anim.Rebind();
			_f.anim.Play("TakeOff", 0, 0f);
			_f.anim.Update(0f);
			SetState(1);
			_t = 0f;
			_mode = Mode.Climbing;
		}

		private void ClimbingTick(float dt)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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_00ae: 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)
			_t += dt;
			float num = Mathf.Lerp(1.5f, 7f, Mathf.Clamp01(_t / 1.3f));
			float num2 = Mathf.Lerp(1.3f, 0.25f, Mathf.Clamp01(_t / 1.5f));
			_vel = Quaternion.Euler(0f, _yaw, 0f) * Vector3.forward * num + Vector3.up * num2;
			Transform root = Root;
			root.position += (_vel + W.BoatVelocity) * dt;
			if (_t < 1.3f)
			{
				return;
			}
			_wingAt = _now + 0.6f;
			switch (_then)
			{
			case Then.Hover:
				_mode = Mode.ToHover;
				return;
			case Then.Fish:
			case Then.Snack:
				_carryFish = _then == Then.Fish;
				_sideSign = ((Random.value < 0.5f) ? 1f : (-1f));
				_mode = Mode.ToDive;
				return;
			case Then.Leave:
				BeginCircle();
				return;
			}
			if (_landOn == null || !_landOn.Ok)
			{
				_landOn = PickHigh();
			}
			_landStage = 0;
			_mode = Mode.ToLand;
		}

		private static Vector3 Flat(Vector3 v)
		{
			//IL_0022: 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)
			v.y = 0f;
			if (!(((Vector3)(ref v)).sqrMagnitude > 1E-06f))
			{
				return Vector3.forward;
			}
			return ((Vector3)(ref v)).normalized;
		}

		private void Steer(Vector3 target, float maxSpeed, float dt, bool free = false)
		{
			//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)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_008c: 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_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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = target - Root.position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			Vector3 val2 = ((magnitude > 0.01f) ? (val / magnitude * Mathf.Min(maxSpeed, 0.5f + magnitude * 1.1f)) : Vector3.zero);
			_vel = Vector3.MoveTowards(_vel, val2, 9f * dt);
			Vector3 val3 = (free ? _vel : (_vel + W.BoatVelocity));
			Transform root = Root;
			root.position += val3 * dt;
			Attitude(val3, dt);
			Wings(val3);
		}

		private void Attitude(Vector3 world, float dt)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = new Vector2(world.x, world.z);
			float magnitude = ((Vector2)(ref val)).magnitude;
			float num = ((magnitude > 1f) ? (Mathf.Atan2(world.x, world.z) * 57.29578f) : _yaw);
			float num2 = Mathf.Clamp(Mathf.DeltaAngle(_yaw, num), -110f * dt, 110f * dt);
			_yaw += num2;
			_bank = Mathf.Lerp(_bank, Mathf.Clamp(num2 / dt * 0.4f, -38f, 38f), dt * 3f);
			_pitch = Mathf.Lerp(_pitch, Mathf.Clamp(Mathf.Atan2(world.y, Mathf.Max(magnitude, 2f)) * 57.29578f, -25f, 28f), dt * 3f);
			ApplyTurn();
		}

		private void ApplyTurn()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Root.rotation = Quaternion.Euler(0f, _yaw, 0f) * Quaternion.Euler(0f - _pitch, 0f, 0f - _bank);
		}

		private void Wings(Vector3 world)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (!(_now < _wingAt))
			{
				bool flag = world.y > 0.6f || ((Vector3)(ref world)).magnitude < 7f || Random.value < 0.3f;
				SetState(flag ? 1 : 0);
				_wingAt = _now + Random.Range(1.5f, 3.5f);
			}
		}

		private Vector3 LandPos(float tau)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: 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_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0044: 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_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)
			//IL_005b: 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_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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			Quaternion turn = _landOn.Turn;
			Vector3 val = Flat(turn * Vector3.forward);
			Vector3 val2 = _landOn.World + turn * (_pSettle * _size) - turn * (_fLand * _size);
			float num = (_landOn.Steep ? 3.2f : 7f);
			float num2 = (_landOn.Steep ? 2.2f : 0.6f);
			return val2 + Vector3.up * (num2 * tau * tau / 3.2f) - val * (num * tau * tau / 3.2f);
		}

		private void ToLandTick(float dt)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: 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_0092: 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_00a2: 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_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			if (_want != null)
			{
				_landOn = _want;
				_want = null;
				_landStage = 0;
			}
			if (_landOn == null || !_landOn.Ok)
			{
				_landOn = PickHigh();
			}
			if (_landOn == null)
			{
				BeginCircle();
				return;
			}
			Vector3 val = LandPos(1.6f);
			Vector3 val2 = Flat(_landOn.Turn * Vector3.forward);
			if (_landStage == 0)
			{
				Vector3 val3 = (_landOn.Steep ? (val - val2 * 2f + Vector3.up * 5f) : (val - val2 * 7f + Vector3.up * 4f));
				Steer(val3, 13f, dt);
				if (Vector3.Distance(Root.position, val3) < 3.5f)
				{
					_landStage = 1;
				}
				return;
			}
			Steer(val, (_landOn.Steep ? 4f : 7f) + 1f, dt);
			if (!(Vector3.Distance(Root.position, val) >= 1.3f))
			{
				_landLeft = 1.6f;
				_landOff = Root.position - val;
				_state = 9;
				_f.anim.SetInteger("State", 9);
				_f.anim.CrossFade("Land", 0.1f, 0, 0f);
				_mode = Mode.Landing;
			}
		}

		private void LandingTick(float dt)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			if (_landOn == null || !_landOn.Ok)
			{
				BeginCircle();
				return;
			}
			_landLeft = Mathf.Max(0f, _landLeft - dt);
			float landLeft = _landLeft;
			float num = landLeft / 1.6f;
			Root.position = LandPos(landLeft) + _landOff * (num * num);
			float num2 = 1f - num;
			num2 = num2 * num2 * (3f - 2f * num2);
			Root.rotation = Quaternion.Slerp(Quaternion.Euler(0f, _yaw, 0f) * Quaternion.Euler(0f - _pitch, 0f, 0f - _bank), _landOn.Turn, num2);
			if (!(landLeft > 0f))
			{
				_perch = _landOn;
				Hang(_perch.Parent);
				Show(_p);
				Root.localPosition = _perch.Local;
				Root.localRotation = _perch.LocalTurn;
				_p.anim.Rebind();
				_state = 0;
				_p.anim.SetInteger("State", 0);
				_p.anim.Play("Settle", 0, 0f);
				_p.anim.Update(0f);
				_since = 0f;
				_holdUntil = _now + 3f;
				_mode = Mode.Perched;
				W.Note("she lands on " + _perch.Name + " at " + ((Vector3)(ref _perch.Local)).ToString("F1") + ", " + Vector3.Distance(_perch.World, W.PlayerFeet).ToString("F1") + " m from you.");
			}
		}

		private void ToHoverTick(float dt)
		{
			//IL_004b: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if (!W.HiddenLand)
			{
				_landOn = ((_perch != null && _perch.Ok) ? _perch : PickHigh());
				_landStage = 0;
				_mode = Mode.ToLand;
				return;
			}
			Vector3 hoverSpot = W.HoverSpot;
			Steer(hoverSpot, 9f, dt);
			if (!(Vector3.Distance(Root.position, hoverSpot) > 3f))
			{
				_mode = Mode.Hovering;
				_clearFor = 0f;
				_crying = false;
				_holdUntil = _now + 2f;
				_underNow = false;
				SetState(2);
				W.Note("the booby hangs over the bow, pointing at the land she can sense.");
			}
		}

		private bool PlayerUnder()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (!W.PlayerAboard)
			{
				return false;
			}
			Vector3 val = Root.position - W.PlayerFeet;
			float y = val.y;
			val.y = 0f;
			if (((Vector3)(ref val)).magnitude <= W.LookDownWithin)
			{
				return y >= 1.2f;
			}
			return false;
		}

		private void HoveringTick(float dt)
		{
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_003e: 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_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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			Vector3 hoverSpot = W.HoverSpot;
			_vel = Vector3.ClampMagnitude((hoverSpot - Root.position) * 1.4f, 4f);
			Transform root = Root;
			root.position += (_vel + W.BoatVelocity) * dt;
			bool flag = PlayerUnder();
			Vector3 val = (flag ? Flat(W.PlayerFeet - Root.position) : W.LandBearing);
			float num = Mathf.Atan2(val.x, val.z) * 57.29578f;
			_yaw += Mathf.Clamp(Mathf.DeltaAngle(_yaw, num), -70f * dt, 70f * dt);
			_pitch = Mathf.Lerp(_pitch, 0f, dt * 3f);
			_bank = Mathf.Lerp(_bank, 0f, dt * 3f);
			ApplyTurn();
			if (_crying)
			{
				string s = (_underNow ? "HoverDownCry" : "HoverCry");
				string s2 = (_underNow ? "HoverDown" : "Hover");
				if (!_cryIn)
				{
					if (Entered(s))
					{
						_cryIn = true;
						Sound("bird_alarm", 0.25f);
						SetState(_underNow ? 4 : 2);
					}
					else if (_now > _timeout)
					{
						_crying = false;
					}
				}
				else if (In(s2) || _now > _timeout)
				{
					_crying = false;
					_holdUntil = _now + Random.Range(20f, 40f);
				}
				return;
			}
			_underNow = flag;
			SetState(flag ? 4 : 2);
			if (!W.HiddenLand && !_leave)
			{
				_clearFor += dt;
				if (_clearFor > 8f)
				{
					_landOn = ((_perch != null && _perch.Ok) ? _perch : PickHigh());
					_landStage = 0;
					_mode = Mode.ToLand;
					return;
				}
			}
			else
			{
				_clearFor = 0f;
			}
			if (_leave)
			{
				BeginCircle();
			}
			else if (_now >= _holdUntil && In(flag ? "HoverDown" : "Hover"))
			{
				_crying = true;
				_cryIn = false;
				_timeout = _now + 6f;
				SetState(flag ? 6 : 5);
			}
		}

		private Vector3 DiveStart()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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)
			Vector3 boatBow = W.BoatBow;
			Vector3 val = Vector3.Cross(Vector3.up, boatBow) * _sideSign;
			Vector3 val2 = W.BoatPos + val * (W.HalfBeam + 10f) + boatBow * 3f;
			val2.y = W.SeaY(val2) + 14f;
			return val2;
		}

		private void ToDiveTick(float dt)
		{
			//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)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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)
			Vector3 val = DiveStart();
			Steer(val, 12f, dt);
			if (!(Vector3.Distance(Root.position, val) > 3f))
			{
				Vector3 val2 = W.BoatBow * 0.5f + Vector3.down * 0.86f;
				Vector3 normalized = ((Vector3)(ref val2)).normalized;
				_vel = normalized * 14f;
				SetState(3);
				_mode = Mode.Diving;
				_yaw = Mathf.Atan2(normalized.x, normalized.z) * 57.29578f;
			}
		}

		private void DivingTick(float dt)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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)
			Transform root = Root;
			root.position += (_vel + W.BoatVelocity) * dt;
			Root.rotation = Quaternion.Slerp(Root.rotation, Quaternion.LookRotation(((Vector3)(ref _vel)).normalized, Vector3.up), dt * 6f);
			if (!(Root.position.y > W.SeaY(Root.position) + 0.15f))
			{
				W.Splash(Root.position);
				_f.go.SetActive(false);
				_t = 0f;
				_mode = Mode.Under;
			}
		}

		private void UnderTick(float dt)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_008e: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: 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_0134: 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)
			_t += dt;
			Transform root = Root;
			root.position += W.BoatVelocity * dt;
			if (!(_t < 0.8f))
			{
				_f.go.SetActive(true);
				_state = -1;
				_lastClip = 0;
				_pitch = 20f;
				_bank = 0f;
				Vector3 val = Flat(W.BoatPos - Root.position);
				_yaw = Mathf.Atan2(val.x, val.z) * 57.29578f;
				ApplyTurn();
				_f.anim.Rebind();
				_f.anim.Play("TakeOff", 0, 0f);
				_f.anim.Update(0f);
				SetState(1);
				W.Splash(Root.position);
				_vel = Vector3.up * 3f + val * 2f;
				_wingAt = _now + 3f;
				if (!_carryFish)
				{
					W.Snacked();
					_landOn = ((_perch != null && _perch.Ok) ? _perch : PickHigh());
					_landStage = 0;
					_mode = Mode.ToLand;
				}
				else
				{
					W.PickDeckSpot();
					Carry(on: true);
					_mode = Mode.Carrying;
				}
			}
		}

		private void CarryingTick(float dt)
		{
			//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_0021: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = W.DeckSpot + Vector3.up * 2.4f;
			Steer(val, 8f, dt);
			if (!(Vector3.Distance(Root.position, val) > 1.6f))
			{
				_t = 0f;
				SetState(2);
				_mode = Mode.Dropping;
			}
		}

		private void DroppingTick(float dt)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0060: 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_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			_t += dt;
			Vector3 val = W.DeckSpot + Vector3.up * 2.4f;
			_vel = Vector3.ClampMagnitude((val - Root.position) * 1.4f, 3f);
			Transform root = Root;
			root.position += (_vel + W.BoatVelocity) * dt;
			_pitch = Mathf.Lerp(_pitch, 0f, dt * 3f);
			_bank = Mathf.Lerp(_bank, 0f, dt * 3f);
			ApplyTurn();
			if (!(_t < 0.8f))
			{
				Carry(on: false);
				W.DropFish(W.DeckSpot + Vector3.up * 0.9f);
				W.Note("the booby drops a fish on the deck.");
				_eatNext = true;
				_landOn = ((_perch != null && _perch.Ok) ? _perch : PickHigh());
				_landStage = 0;
				_wingAt = _now + 0.4f;
				_mode = Mode.ToLand;
			}
		}

		private void Carry(bool on)
		{
			//IL_00a7: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_00b1: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: 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)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: 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_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: 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_01c9: 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)
			if ((Object)(object)_carry != (Object)null)
			{
				W.Remove(_carry);
				_carry = null;
			}
			if (on && !((Object)(object)_f.jaw == (Object)null))
			{
				_carry = W.FishLook();
				if (!((Object)(object)_carry == (Object)null))
				{
					Vector3 val = (_f.hasTip ? _f.jaw.TransformPoint(_f.tip) : (_f.jaw.position + Root.forward * 0.12f));
					Vector3 val2 = val - _f.jaw.position;
					Vector3 normalized = ((Vector3)(ref val2)).normalized;
					MeshFilter component = _carry.GetComponent<MeshFilter>();
					Bounds val3 = (Bounds)(((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null) ? component.sharedMesh.bounds : new Bounds(Vector3.zero, Vector3.forward));
					Vector3 size = ((Bounds)(ref val3)).size;
					Vector3 val4 = ((size.x >= size.y && size.x >= size.z) ? Vector3.right : ((size.y >= size.z) ? Vector3.up : Vector3.forward));
					Vector3 lossyScale = _carry.transform.lossyScale;
					Quaternion val5 = Quaternion.FromToRotation(val4, normalized);
					_carry.transform.rotation = val5;
					Transform transform = _carry.transform;
					val2 = Vector3.Scale(size, lossyScale);
					transform.position = val + normalized * (((Vector3)(ref val2)).magnitude * 0.25f) - val5 * Vector3.Scale(((Bounds)(ref val3)).center, lossyScale);
					_carry.transform.SetParent(_f.jaw, true);
				}
			}
		}

		private static void FindTip(Body b)
		{
			//IL_007f: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: 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)
			if ((Object)(object)b.jaw == (Object)null || (Object)(object)b.smr == (Object)null || (Object)(object)b.smr.sharedMesh == (Object)null || !b.smr.sharedMesh.isReadable)
			{
				return;
			}
			Mesh sharedMesh = b.smr.sharedMesh;
			int num = Array.IndexOf(b.smr.bones, b.jaw);
			if (num < 0)
			{
				return;
			}
			Vector3[] vertices = sharedMesh.vertices;
			BoneWeight[] boneWeights = sharedMesh.boneWeights;
			Matrix4x4 val = sharedMesh.bindposes[num];
			float num2 = -1f;
			for (int i = 0; i < vertices.Length && i < boneWeights.Length; i++)
			{
				if (((BoneWeight)(ref boneWeights[i])).boneIndex0 == num && !(((BoneWeight)(ref boneWeights[i])).weight0 < 0.9f))
				{
					Vector3 tip = ((Matrix4x4)(ref val)).MultiplyPoint3x4(vertices[i]);
					float sqrMagnitude = ((Vector3)(ref tip)).sqrMagnitude;
					if (sqrMagnitude > num2)
					{
						num2 = sqrMagnitude;
						b.tip = tip;
						b.hasTip = true;
					}
				}
			}
		}

		private void BeginCircle()
		{
			//IL_0086: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			_leave = false;
			Carry(on: false);
			if (_cur != _f)
			{
				Hang(W.FlightParent);
				Show(_f);
				_f.anim.Rebind();
				_f.anim.Play("Flap", 0, 0f);
				_f.anim.Update(0f);
				SetState(1);
			}
			Vector3 val = Root.position - W.BoatPos;
			_ang = Mathf.Atan2(val.z, val.x);
			_swept = 0f;
			_mode = Mode.Circling;
			_wingAt = _now + 1f;
			W.Note("the booby leaves: once round the ship, and away.");
		}

		private void CirclingTick(float dt)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0096: 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_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			float num = 11f / 30f * dt;
			_ang += num;
			_swept += num;
			Vector3 val = W.BoatPos + new Vector3(Mathf.Cos(_ang), 0f, Mathf.Sin(_ang)) * 30f;
			val.y = W.SeaY(val) + 17f;
			Steer(val, 13f, dt);
			if (!(_swept < (float)Math.PI * 2f))
			{
				_vel += W.BoatVelocity;
				_t = 0f;
				Vector3 val2 = (W.LandNear ? (-W.LandBearing) : Flat(_vel));
				_awayDir = Vector3.Slerp(Flat(_vel), val2, 0.6f);
				_mode = Mode.Away;
			}
		}

		private void AwayTick(float dt)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_002f: 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_003e: 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)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			_t += dt;
			Steer(Root.position + _awayDir * 60f + Vector3.up * 4f, 13f, dt, free: true);
			if (_t > 70f || Vector3.Distance(Root.position, W.BoatPos) > 650f)
			{
				_mode = Mode.Gone;
				W.Note("the booby is out of sight.");
			}
		}
	}
	internal class BirdKeeper : MonoBehaviour
	{
		private enum Stage
		{
			None,
			Visiting,
			Yours,
			Leaving
		}

		private const string BundleFile = "furstbird";

		private const string PerchPath = "assets/furstbird/birdperch.prefab";

		private const string FlyPath = "assets/furstbird/birdfly.prefab";

		private const string SaveKey = "FurstMate.bird";

		private const float SeaMile = 150f;

		private const float MsToKnots = 1.944f;

		internal static BirdKeeper Instance;

		internal ConfigEntry<bool> Enabled;

		internal ConfigEntry<bool> OnYards;

		internal ConfigEntry<bool> NeedsFeeding;

		internal ConfigEntry<string> BirdName;

		internal ConfigEntry<float> BirdSize;

		internal ConfigEntry<float> ChanceAMinute;

		internal ConfigEntry<float> ComesOverKnots;

		internal ConfigEntry<float> LeavesUnderKnots;

		internal ConfigEntry<float> OpenWater;

		internal ConfigEntry<float> LandWithin;

		internal ConfigEntry<float> LeavesWithin;

		internal ConfigEntry<float> AgainMinutes;

		internal ConfigEntry<float> VisitMin;

		internal ConfigEntry<float> VisitMax;

		internal ConfigEntry<float> NorthOfOasis;

		internal ConfigEntry<float> FogAt;

		internal ConfigEntry<float> RainAt;

		internal ConfigEntry<float> FishMinutes;

		internal ConfigEntry<float> SnackMinutes;

		internal ConfigEntry<float> SnackFeeds;

		internal ConfigEntry<float> BellyDays;

		internal ConfigEntry<float> GoneAfterDays;

		internal ConfigEntry<float> LookDownWithin;

		internal ConfigEntry<float> WingsHeardTo;

		internal ConfigEntry<float> CallsHeardTo;

		internal ConfigEntry<int> TriesMax;

		internal ConfigEntry<int> CallVolume;

		internal ConfigEntry<int> WingVolume;

		private ConfigEntry<bool> ResetTries;

		private ConfigEntry<bool> BringNow;

		private ConfigEntry<bool> TameNow;

		private ConfigEntry<bool> FishNow;

		private ConfigEntry<bool> SnackNow;

		private ConfigEntry<bool> AwayNow;

		private ConfigEntry<bool> EmptyBellyNow;

		private ConfigEntry<bool> PretendFog;

		private ConfigEntry<bool> PretendLand;

		private ConfigEntry<bool> PretendStorm;

		private ConfigEntry<bool> ShowPerches;

		private ConfigEntry<bool> ReadPerchesNow;

		private GameObject _perchPrefab;

		private GameObject _flyPrefab;

		private AssetBundle _bundle;

		internal BirdFlight Bird;

		private GameBird _world;

		private BoatRefs _shipOf;

		private BirdPerches _perches;

		private bool _scanning;

		private bool _soundsLoaded;

		private Stage _stage;

		private int _tries;

		internal float Food = 100f;

		private float _zeroHours;

		private bool _placeNext;

		private bool _inYard;

		private float _tick;

		private float _nextAt;

		private float _rollAt;

		private float _fastSince = -1f;

		private float _slowSince = -1f;

		private float _fishAt;

		private float _snackAt;

		private float _readAt;

		private float _visitStart = -1f;

		private float _visitLen;

		private float _elsewhereSince = -1f;

		private float _nearUntil;

		private float _moveAt;

		private int _phase;

		private readonly List<GameObject> _marks = new List<GameObject>();

		private GoPointer _pointer;

		private GameObject _board;

		private Transform _foodFill;

		private Renderer _foodFillR;

		private float _boardUntil;

		internal bool ForceFog => PretendFog.Value;

		internal bool ForceLand => PretendLand.Value;

		internal bool ForceStorm => PretendStorm.Value;

		internal bool Tamed => _stage == Stage.Yours;

		internal string Called
		{
			get
			{
				if (!string.IsNullOrWhiteSpace(BirdName.Value))
				{
					return BirdName.Value.Trim();
				}
				return "The booby";
			}
		}

		private bool Feeding => NeedsFeeding.Value;

		internal void Setup(ConfigFile cfg, Harmony h)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Expected O, but got Unknown
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Expected O, but got Unknown
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: Expected O, but got Unknown
			//IL_05a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ad: Expected O, but got Unknown
			//IL_05d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05e3: Expected O, but got Unknown
			//IL_060b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0619: Expected O, but got Unknown
			Instance = this;
			Enabled = cfg.Bind<bool>("Bird", "A wild booby may come aboard", true, "Off: no bird comes, and one aboard flies off.");
			BirdName = cfg.Bind<string>("Bird", "Name", "The booby", "What her look text and her messages call her, once she has stayed.");
			BirdSize = cfg.Bind<float>("Bird", "Size", 1f, new ConfigDescription("Against the model: at 1 she stands 55 cm and has 1.52 m of wing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.7f, 1.5f), Array.Empty<object>()));
			CallVolume = cfg.Bind<int>("Bird", "Call volume (1 to 100)", 50, new ConfigDescription("Her calls and cries.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			WingVolume = cfg.Bind<int>("Bird", "Wing volume (1 to 100)", 35, new ConfigDescription("Her wingbeats.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>()));
			WingsHeardTo = cfg.Bind<float>("Bird", "Her wings are heard out to (m)", 25f, "Full within 3 m, fading to nothing at this distance, so that you hear her fly only when she is close. Her calls carry further: see the next setting. Takes effect the next time she comes aboard.");
			CallsHeardTo = cfg.Bind<float>("Bird", "Her calls are heard out to (m)", 60f, new ConfigDescription("Full within a thirtieth of this (2 m at 60), half as loud by a seventh (8 m), a quarter by a third (20 m), a tenth by two thirds (40 m), and nothing beyond it. Changes as you listen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 220f), Array.Empty<object>()));
			ChanceAMinute = cfg.Bind<float>("Bird", "Chance a minute that she comes (percent)", 40f, new ConfigDescription("High, because the dice only roll in warm open water, under way, with her tries not used up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			ComesOverKnots = cfg.Bind<float>("Bird", "She comes when you sail over (knots)", 3f, "By the game's knots, held for a minute.");
			OpenWater = cfg.Bind<float>("Bird", "Open water is over (sea miles from land)", 40f, "A sea mile is 150 m of the game's world (the chart has 60 to a degree, a degree is 9 km). 40 is 6 km.");
			NorthOfOasis = cfg.Bind<float>("Bird", "Her waters reach north of Oasis by (degrees)", 2f, "Warm water: she comes only south of the chart's latitude of the port of Oasis, plus this. 90: anywhere.");
			VisitMin = cfg.Bind<float>("Bird", "A visit lasts at least (minutes)", 10f, "Real minutes. Three times in it she comes down within your reach.");
			VisitMax = cfg.Bind<float>("Bird", "A visit lasts at most (minutes)", 15f, "Real minutes.");
			TriesMax = cfg.Bind<int>("Bird", "Tries before she stops coming", 3, "Visits you let pass without feeding her. Reset below, and when a bird of yours goes off hungry.");
			ResetTries = cfg.Bind<bool>("Bird", "Reset her tries now", false, "She may come again, and this switches itself off again.");
			AgainMinutes = cfg.Bind<float>("Bird", "Before she tries again (minutes)", 30f, "Real minutes after she has flown off.");
			NeedsFeeding = cfg.Bind<bool>("Bird", "Once she stays she needs feeding", true, "Off: she never goes hungry.");
			BellyDays = cfg.Bind<float>("Bird", "A full belly lasts (game days)", 14f, "From full to nothing, with no diving for herself.");
			SnackMinutes = cfg.Bind<float>("Bird", "She dives for herself about every (minutes)", 15f, "Under way in calm weather, real minutes, give or take a third.");
			SnackFeeds = cfg.Bind<float>("Bird", "A dive feeds her (percent)", 1f, new ConfigDescription("What each small fish adds to her food meter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 25f), Array.Empty<object>()));
			GoneAfterDays = cfg.Bind<float>("Bird", "At no food she goes after (game days)", 2f, "Then she is gone one morning, gone to look for food. Her tries start again, and she may turn up again.");
			LandWithin = cfg.Bind<float>("Bird", "She senses land within (sea miles)", 75f, "She wakes, paces and calls. 75 is 11 km, about where an island sinks below your horizon.");
			LeavesUnderKnots = cfg.Bind<float>("Bird", "A visitor leaves when you slow under (knots)", 1f, "Near land only: see the next line. That is no try used up.");
			LeavesWithin = cfg.Bind<float>("Bird", "A visitor leaves when slow within (sea miles of land)", 20f, "Becalmed further out than this, she stays. A bird who has stayed stays anywhere.");
			FogAt = cfg.Bind<float>("Bird", "Thick fog at density", 0.015f, "The game's own fog density, where it starts showing its fog effects.");
			RainAt = cfg.Bind<float>("Bird", "Heavy rain at strength", 0.6f, new ConfigDescription("How far into the game's rain weather, 0 to 1.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			FishMinutes = cfg.Bind<float>("Bird", "She brings a fish about every (minutes)", 25f, "In calm weather, aboard, not when she is hungry. Real minutes, give or take a third.");
			LookDownWithin = cfg.Bind<float>("Bird", "She looks down at you within (m)", 5f, "Hanging in the air this close over your head (level distance), she bends her neck and looks at you.");
			OnYards = cfg.Bind<bool>("Bird", "She may perch on square yards", true, "Their ends, swinging with them.");
			BringNow = cfg.Bind<bool>("Testing", "Bring the bird now", false, "A visit starts at once, anywhere, and this switches itself off again. For testing.");
			TameNow = cfg.Bind<bool>("Testing", "Tame the bird now", false, "As if you had fed her, and this switches itself off again. For testing.");
			EmptyBellyNow = cfg.Bind<bool>("Testing", "Empty the bird belly now", false, "Her food meter goes to nothing, and this switches itself off again. For testing.");
			FishNow = cfg.Bind<bool>("Testing", "Send the bird fishing now", false, "And this switches itself off again. For testing.");
			SnackNow = cfg.Bind<bool>("Testing", "Send the bird diving for herself now", false, "And this switches itself off again. For testing.");
			AwayNow = cfg.Bind<bool>("Testing", "Send the bird away now", false, "Once round the ship and off, and this switches itself off again. No try used up. For testing.");
			PretendFog = cfg.Bind<bool>("Testing", "Pretend fog and hidden land for the bird", false, "She hangs over the bow, facing the nearest land. For testing.");
			PretendLand = cfg.Bind<bool>("Testing", "Pretend land is near for the bird", false, "She paces and calls. For testing.");
			PretendStorm = cfg.Bind<bool>("Testing", "Pretend a severe storm for the bird", false, "She goes to her low place and hunkers. For testing.");
			ShowPerches = cfg.Bind<bool>("Testing", "Show the bird perches", false, "A small ball on each place she found on the ship she is aboard: red mast top or platform, blue bow, yellow yard, green low, white rails. For testing.");
			ShowPerches.SettingChanged += delegate
			{
				Marks();
			};
			ReadPerchesNow = cfg.Bind<bool>("Testing", "Read the bird perches of every ship", false, "Looks over every ship in the world as she would and writes to the log what she found on each, and any rail that does not look like one. Takes under a minute and switches itself off. Changes nothing in play.");
			try
			{
				h.Patch((MethodBase)AccessTools.Method(typeof(SaveLoadManager), "SaveModData", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(BirdKeeper), "AfterSaveModData", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				h.Patch((MethodBase)AccessTools.Method(typeof(SaveLoadManager), "LoadModData", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(BirdKeeper), "AfterLoadModData", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				h.Patch((MethodBase)AccessTools.Method(typeof(SaveLoadManager), "LoadGame", (Type[])null, (Type[])null), new HarmonyMethod(typeof(BirdKeeper), "BeforeLoadGame", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			catch (Exception ex)
			{
				FurstMatePlugin.Log.LogWarning((object)("FurstMate: the bird's place in the save - " + ex.Message));
			}
			LoadBundle();
		}

		private void LoadBundle()
		{
			string text = Path.Combine(Path.GetDirectoryName(typeof(BirdKeeper).Assembly.Location) ?? "", "furstbird");
			if (!File.Exists(text))
			{
				FurstMatePlugin.Log.LogWarning((object)"FurstMate: no bird: the file 'furstbird' must sit beside FurstMate.dll.");
				return;
			}
			try
			{
				_bundle = AssetBundle.LoadFromFile(text);
				if ((Object)(object)_bundle != (Object)null)
				{
					_perchPrefab = _bundle.LoadAsset<GameObject>("assets/furstbird/birdperch.prefab");
					_flyPrefab = _bundle.LoadAsset<GameObject>("assets/furstbird/birdfly.prefab");
				}
			}
			catch (Exception ex)
			{
				FurstMatePlugin.Log.LogWarning((object)("FurstMate: the bird would not load - " + ex.Message));
			}
			if ((Object)(object)_perchPrefab == (Object)null || (Object)(object)_flyPrefab == (Object)null)
			{
				_perchPrefab = (_flyPrefab = null);
				FurstMatePlugin.Log.LogWarning((object)"FurstMate: no bird: the bundle lacks her two bodies.");
				return;
			}
			Shader val = Shader.Find("Standard");
			GameObject[] array = (GameObject[])(object)new GameObject[2] { _perchPrefab, _flyPrefab };
			for (int i = 0; i < array.Length; i++)
			{
				Renderer[] componentsInChildren = array[i].GetComponentsInChildren<Renderer>(true);
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					Material[] sharedMaterials = componentsInChildren[j].sharedMaterials;
					foreach (Material val2 in sharedMaterials)
					{
						if ((Object)(object)val2 != (Object)null && (Object)(object)val != (Object)null && (Object)(object)val2.shader != (Object)null && ((Object)val2.shader).name == "Standard")
						{
							val2.shader = val;
						}
					}
				}
			}
			FurstMatePlugin.Log.LogInfo((object)"FurstMate: the booby is loaded.");
		}

		private void LateUpdate()
		{
			if (Bird == null)
			{
				return;
			}
			try
			{
				if ((Object)(object)Bird.Root == (Object)null)
				{
					ForgetBird();
				}
				else if (GameState.playing && !GameState.currentlyLoading)
				{
					_world.Tick(Time.deltaTime);
					Bird.Tick(Time.deltaTime);
					PlaceBoard();
				}
			}
			catch (Exception ex)
			{
				FurstMatePlugin.Log.LogWarning((object)("FurstMate: the bird - " + ex.Message + "\n" + ex.StackTrace));
				ForgetBird();
			}
		}

		private void Update()
		{
			if ((Object)(object)_perchPrefab == (Object)null)
			{
				return;
			}
			if (ResetTries.Value)
			{
				ResetTries.Value = false;
				_tries = 0;
				_nextAt = 0f;
				FurstMatePlugin.Note("The booby's tries are reset: she may come again.");
			}
			if (FishNow.Value)
			{
				FishNow.Value = false;
				if (Bird != null)
				{
					Bird.GoFish();
				}
				else
				{
					FurstMatePlugin.Note("There is no bird aboard.");
				}
			}
			if (SnackNow.Value)
			{
				SnackNow.Value = false;
				if (Bird != null)
				{
					Bird.GoSnack();
				}
				else
				{
					FurstMatePlugin.Note("There is no bird aboard.");
				}
			}
			if (AwayNow.Value)
			{
				AwayNow.Value = false;
				if (Bird != null)
				{
					if (_stage == Stage.Visiting)
					{
						_stage = Stage.Leaving;
					}
					Bird.Leave();
				}
				else
				{
					FurstMatePlugin.Note("There is no bird aboard.");
				}
			}
			if (TameNow.Value)
			{
				TameNow.Value = false;
				if (_stage == Stage.Visiting)
				{
					Tame();
					FurstMatePlugin.Note(Called + " has stayed (testing).");
				}
				else if (_stage != Stage.Yours)
				{
					_stage = Stage.Yours;
					Food = 100f;
					_zeroHours = 0f;
					_tries = 0;
					FurstMatePlugin.Note(Called + " is yours and will come to your ship (testing).");
				}
			}
			if (EmptyBellyNow.Value)
			{
				EmptyBellyNow.Value = false;
				Food = 0f;
				FurstMatePlugin.Note("The booby's belly is empty (testing).");
			}
			if (ReadPerchesNow.Value && GameState.playing && !GameState.currentlyLoading)
			{
				ReadPerchesNow.Value = false;
				((MonoBehaviour)this).StartCoroutine(ReadEveryShip());
				FurstMatePlugin.Note("Reading the bird perches of every ship: it goes in the log.");
			}
			if (_stage == Stage.Yours && Feeding && (Object)(object)Sun.sun != (Object)null && !Sun.SunPaused())
			{
				float num = Time.deltaTime * Sun.sun.timescale;
				if (Food > 0f)
				{
					Food = Mathf.Max(0f, Food - num * 100f / (24f * Mathf.Max(0.05f, BellyDays.Value)));
					_zeroHours = 0f;
				}
				else
				{
					_zeroHours += num;
				}
			}
			if (Time.time < _tick)
			{
				return;
			}
			_tick = Time.time + 1f;
			try
			{
				Tick();
			}
			catch (Exception ex)
			{
				FurstMatePlugin.Log.LogWarning((object)("FurstMate: the bird - " + ex.Message + "\n" + ex.StackTrace));
			}
		}

		private void Tick()
		{
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0332: Unknown result type (might be due to invalid IL or missing references)
			bool flag = (Object)(object)GameState.currentShipyard != (Object)null;
			if (flag != _inYard)
			{
				_inYard = flag;
				if (flag && Bird != null && (Object)(object)_shipOf != (Object)null && (Object)(object)Bird.Root != (Object)null && !Bird.IsGone && (Object)(object)FurstMatePlugin.BoatOf(((Object)(object)GameState.currentShipyard.GetCurrentBoat() != (Object)null) ? GameState.currentShipyard.GetCurrentBoat().transform : null) == (Object)(object)_shipOf)
				{
					if (_stage == Stage.Visiting)
					{
						EndVisit(aTry: false);
					}
					else
					{
						_placeNext = false;
						Bird.Leave();
					}
					FurstMatePlugin.Log.LogInfo((object)("FurstMate: the " + ((Object)_shipOf).name + " is in the shipyard: the booby flies off and will read the ship afresh."));
				}
			}
			if (!GameState.playing || GameState.currentlyLoading)
			{
				return;
			}
			BoatRefs val = FurstMatePlugin.BoatOf(GameState.currentBoat);
			bool flag2 = (Object)(object)val != (Object)null && (Object)(object)val.walkCol != (Object)null && FurstMatePlugin.Owned(val);
			if (_stage == Stage.Yours && Feeding && Food <= 0f && _zeroHours >= GoneAfterDays.Value * 24f && IsMorning() && (Bird == null || !Bird.Flying))
			{
				GoneHungry();
			}
			else if (Bird != null && Bird.IsGone)
			{
				ForgetBird();
				if (_stage == Stage.Leaving)
				{
					_stage = Stage.None;
				}
			}
			else if (Bird != null)
			{
				WithBird(val, flag2);
			}
			else
			{
				if (_scanning)
				{
					return;
				}
				if (!Enabled.Value)
				{
					BringNow.Value = false;
					return;
				}
				if (_inYard)
				{
					_fastSince = -1f;
					return;
				}
				if (_stage == Stage.Yours)
				{
					if (flag2)
					{
						Come(val, _placeNext);
					}
					return;
				}
				if (BringNow.Value)
				{
					if (flag2)
					{
						BringNow.Value = false;
						_stage = Stage.Visiting;
						Come(val, placed: false);
					}
					else if ((Object)(object)val == (Object)null)
					{
						BringNow.Value = false;
						FurstMatePlugin.Note("Stand aboard a ship of yours first.");
					}
					return;
				}
				if (!flag2 || Time.time < _nextAt || _tries >= TriesMax.Value)
				{
					_fastSince = -1f;
					return;
				}
				Rigidbody component = ((Component)val).GetComponent<Rigidbody>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				Vector3 val2 = Flat(component.velocity);
				float num = ((Vector3)(ref val2)).magnitude * 1.944f;
				if (num < ComesOverKnots.Value)
				{
					_fastSince = -1f;
					return;
				}
				if (_fastSince < 0f)
				{
					_fastSince = Time.time;
				}
				if (!(Time.time - _fastSince < 60f) && !(Time.time < _rollAt))
				{
					_rollAt = Time.time + 60f;
					float num2 = (((Object)(object)FloatingOriginManager.instance != (Object)null) ? FloatingOriginManager.instance.GetGlobeCoords(((Component)val).transform).z : 0f);
					float num3 = LatLimit();
					bool flag3 = GameState.distanceToLand >= OpenWater.Value * 150f;
					bool flag4 = num2 <= num3;
					bool flag5 = !GameBird.Storming;
					bool flag6 = flag3 && flag4 && flag5 && Random.value * 100f < ChanceAMinute.Value;
					if ((Object)(object)FurstMatePlugin.Instance != (Object)null && FurstMatePlugin.Instance.LogReadings.Value)
					{
						FurstMatePlugin.Log.LogInfo((object)("FurstMate readings: the bird's chance - " + num.ToString("F1") + " knots, " + (GameState.distanceToLand / 150f).ToString("F0") + " sea miles from land, latitude " + num2.ToString("F1") + " against " + num3.ToString("F1") + ", tries " + _tries + " of " + TriesMax.Value + ", " + (flag6 ? "she comes" : ((!flag3) ? "not open water" : ((!flag4) ? "not warm" : ((!flag5) ? "foul weather" : "not this minute")))) + "."));
					}
					if (flag6)
					{
						_stage = Stage.Visiting;
						Come(val, placed: false);
					}
				}
			}
		}

		private bool IsMorning()
		{
			try
			{
				float num = (((Object)(object)Sun.sun != (Object)null) ? Sun.sun.localTime : 12f);
				return num >= 5f && num <= 9f;
			}
			catch (Exception)
			{
				return true;
			}
		}

		private float LatLimit()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			float num = 30f;
			try
			{
				if (Port.ports != null && (Object)(object)FloatingOriginManager.instance != (Object)null)
				{
					Port[] ports = Port.ports;
					foreach (Port val in ports)
					{
						if ((Object)(object)val != (Object)null && (val.GetPortName() ?? "").IndexOf("oasis", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							num = FloatingOriginManager.instance.GetGlobeCoords(((Component)val).transform).z;
							break;
						}
					}
				}
			}
			catch (Exception)
			{
			}
			return num + NorthOfOasis.Value;
		}

		private void WithBird(BoatRefs here, bool mine)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			if (!Enabled.Value)
			{
				if (_stage != Stage.Yours)
				{
					_stage = Stage.Leaving;
				}
				else
				{
					_stage = Stage.Leaving;
				}
				Bird.Leave();
				return;
			}
			if ((Object)(object)_shipOf == (Object)null)
			{
				ForgetBird();
				return;
			}
			BoatDamage val = ((Component)_shipOf).GetComponent<BoatDamage>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)_shipOf).GetComponentInParent<BoatDamage>();
			}
			bool sunk = (Object)(object)val != (Object)null && val.sunk;
			bool aboard = (Object)(object)here == (Object)(object)_shipOf;
			float fromShip = (((Object)(object)Refs.observerMirror != (Object)null) ? Vector3.Distance(((Component)Refs.observerMirror).transform.position, ((Component)_shipOf).transform.position) : 0f);
			float knots = _world.Knots;
			if (_stage == Stage.Visiting)
			{
				VisitTick(sunk, aboard, fromShip, knots);
			}
			else if (_stage == Stage.Yours)
			{
				YoursTick(here, mine, sunk, aboard);
			}
			if ((Object)(object)FurstMatePlugin.Instance != (Object)null && FurstMatePlugin.Instance.LogReadings.Value && Time.time >= _readAt)
			{
				_readAt = Time.time + 15f;
				FurstMatePlugin.Log.LogInfo((object)("FurstMate readings: the bird, " + _stage.ToString() + ", is " + Bird.Doing + ((Bird.PerchNow != null) ? (" (last perch " + Bird.PerchNow.Name + ")") : "") + "; food " + Food.ToString("F0") + ", tries " + _tries + "; " + knots.ToString("F1") + " knots, land " + (_world.LandMeters / 150f).ToString("F0") + " sea miles, fog " + RenderSettings.fogDensity.ToString("F4") + ", rain " + GameState.rainIntensity.ToString("F2") + ", " + GameBird.WeatherName + " " + GameBird.WeatherLerp.ToString("F2") + ", near " + _world.LandNear + ", hidden " + _world.HiddenLand + ", severe " + _world.Severe + "."));
			}
		}

		private void VisitTick(bool sunk, bool aboard, float fromShip, float knots)
		{
			bool flag = knots < LeavesUnderKnots.Value && GameState.distanceToLand < LeavesWithin.Value * 150f;
			if (!flag)
			{
				_slowSince = -1f;
			}
			else if (_slowSince < 0f)
			{
				_slowSince = Time.time;
			}
			if (sunk || (!aboard && fromShip > 300f) || _world.Severe || GameBird.Storming || (flag && Time.time - _slowSince > 6f))
			{
				EndVisit(aTry: false);
			}
			else
			{
				if (Bird.Flying && _visitStart < 0f)
				{
					return;
				}
				if (_visitStart < 0f)
				{
					_visitStart = Time.time;
					_visitLen = Random.Range(Mathf.Min(VisitMin.Value, VisitMax.Value), Mathf.Max(VisitMin.Value, VisitMax.Value)) * 60f;
					_phase = 0;
					FurstMatePlugin.Log.LogInfo((object)("FurstMate: a wild booby has landed by you (" + Bird.PerchNow.Name + "), for " + (_visitLen / 60f).ToString("F0") + " minutes; try " + (_tries + 1) + " of " + TriesMax.Value + "."));
				}
				float num = (Time.time - _visitStart) / Mathf.Max(1f, _visitLen);
				if (num >= 1f)
				{
					_tries++;
					EndVisit(aTry: true);
					return;
				}
				int num2 = ((!(num < 0.28f)) ? ((num < 0.36f) ? 1 : ((num < 0.64f) ? 2 : ((num < 0.72f) ? 3 : 4))) : 0);
				if (num2 != _phase)
				{
					_phase = num2;
					if (num2 % 2 == 1)
					{
						GoUp();
					}
					else
					{
						ComeDown();
					}
				}
				else if (num2 % 2 == 1 && HoldingFishOrMeat() && Time.time >= _moveAt)
				{
					ComeDown();
				}
			}
		}

		private void EndVisit(bool aTry)
		{
			_stage = Stage.Leaving;
			_visitStart = -1f;
			float num = Mathf.Max(1f, AgainMinutes.Value) * 60f;
			_nextAt = Time.time + (aTry ? num : (num * 0.5f));
			if (aTry)
			{
				FurstMatePlugin.Note((_tries >= TriesMax.Value) ? "The booby flies off, and something tells you she will not try again." : "The booby flies off through the rigging. She may try you again.");
				FurstMatePlugin.Log.LogInfo((object)("FurstMate: the booby was not fed; try " + _tries + " of " + TriesMax.Value + " used."));
			}
			Bird.Leave();
		}

		private void ComeDown()
		{
			_moveAt = Time.time + 20f;
			BirdPerch birdPerch = _world.NearYou();
			if (birdPerch != null)
			{
				Bird.GoTo(birdPerch);
			}
		}

		private void GoUp()
		{
			_moveAt = Time.time + 20f;
			BirdPerch birdPerch = ((_perches != null) ? _perches.AHigh() : null);
			if (birdPerch != null)
			{
				Bird.GoTo(birdPerch);
			}
		}

		private void YoursTick(BoatRefs here, bool mine, bool sunk, bool aboard)
		{
			if (mine && !aboard && !sunk)
			{
				if (_elsewhereSince < 0f)
				{
					_elsewhereSince = Time.time;
				}
				if (Time.time - _elsewhereSince > 20f)
				{
					_elsewhereSince = -1f;
					ForgetBird();
					_placeNext = false;
					return;
				}
			}
			else
			{
				_elsewhereSince = -1f;
			}
			if (sunk)
			{
				Bird.Leave();
			}
			else
			{
				if (!aboard)
				{
					return;
				}
				bool calm = _world.Calm;
				bool flag = !Feeding || Food > 0f;
				if (calm && Bird.IsPerched && flag && Time.time >= _fishAt)
				{
					_fishAt = NextIn(FishMinutes.Value);
					Bird.GoFish();
				}
				if (calm && Bird.IsPerched && _world.Knots >= 1f && Time.time >= _snackAt)
				{
					_snackAt = NextIn(SnackMinutes.Value);
					Bird.GoSnack();
				}
				if (Bird.IsPerched && !_world.Severe && !_world.LandNear && !_world.HiddenLand)
				{
					bool flag2 = HoldingFishOrMeat() || (Feeding && Food < 35f);
					bool flag3 = Bird.PerchNow != null && Bird.PerchNow.WithinReach;
					if (flag2)
					{
						_nearUntil = Time.time + 90f;
					}
					if (flag2 && !flag3 && Time.time >= _moveAt)
					{
						ComeDown();
					}
					else if (!flag2 && flag3 && Time.time >= _nearUntil && Time.time >= _moveAt)
					{
						GoUp();
					}
				}
			}
		}

		private float NextIn(float minutes)
		{
			float num = Mathf.Max(0.5f, minutes) * 60f;
			return Time.time + Random.Range(num * 0.67f, num * 1.33f);
		}

		internal void Snacked()
		{
			if (Feeding)
			{
				Food = Mathf.Clamp(Food + Mathf.Max(0f, SnackFeeds.Value), 0f, 100f);
			}
		}

		private void GoneHungry()
		{
			FurstMatePlugin.Note(Called + " is gone. She has gone to look for food.");
			FurstMatePlugin.Log.LogInfo((object)("FurstMate: the booby went hungry for " + (_zeroHours / 24f).ToString("F1") + " game days and is gone; her tries start again."));
			ForgetBird();
			_stage = Stage.None;
			_tries = 0;
			Food = 100f;
			_zeroHours = 0f;
			_nextAt = Time.time + Mathf.Max(1f, AgainMinutes.Value) * 60f;
		}

		private void Come(BoatRefs boat, bool placed)
		{
			_scanning = true;
			_shipOf = boat;
			_fastSince = -1f;
			_placeNext = false;
			_visitStart = -1f;
			((MonoBehaviour)this).StartCoroutine(ComeAfterScan(boat, placed));
		}

		private IEnumerator ReadEveryShip()
		{
			BoatRefs[] array = Object.FindObjectsOfType<BoatRefs>();
			FurstMatePlugin.Log.LogInfo((object)("FurstMate perch readout: " + array.Length + " ship(s) in the world, reading each in turn."));
			BoatRefs[] array2 = array;
			foreach (BoatRefs val in array2)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)val.walkCol == (Object)null)
				{
					continue;
				}
				string name = ((Object)val).name.Replace("(Clone)", "").Trim();
				BirdPerches scan = new BirdPerches(val, OnYards.Value);
				IEnumerator e = scan.Find();
				bool failed = false;
				while (true)
				{
					bool flag;
					try
					{
						flag = e.MoveNext();
					}
					catch (Exception ex)
					{
						FurstMatePlugin.Log.LogWarning((object)("FurstMate perch readout, " + name + ": " + ex.Message));
						failed = true;
						break;
					}
					if (!flag)
					{
						break;
					}
					yield return e.Current;
				}
				if (!failed)
				{
					string text;
					try
					{
						text = ((scan.All.Count > 0) ? scan.Report() : scan.Stats);
					}
					catch (Exception ex2)
					{
						text = ex2.Message;
					}
					FurstMatePlugin.Log.LogInfo((object)("FurstMate perch readout, " + name + ": " + text + "."));
					yield return null;
				}
			}
			FurstMatePlugin.Log.LogInfo((object)"FurstMate perch readout: done.");
		}

		private IEnumerator ComeAfterScan(BoatRefs boat, bool placed)
		{
			if (!_soundsLoaded && (Object)(object)FurstMatePlugin.Instance != (Object)null)
			{
				_soundsLoaded = true;
				((MonoBehaviour)FurstMatePlugin.Instance).StartCoroutine(DogSounds.LoadBird());
			}
			BirdPerches scan = new BirdPerches(boat, OnYards.Value);
			IEnumerator e = scan.Find();
			while (true)
			{
				bool flag;
				try
				{
					flag = e.MoveNext();
				}
				catch (Exception ex)
				{
					FurstMatePlugin.Log.LogWarning((object)("FurstMate: the bird, looking over the ship - " + ex.Message + "\n" + ex.StackTrace));
					_scanning = false;
					if (_stage == Stage.Visiting)
					{
						_stage = Stage.None