Decompiled source of TheDeadRemain v0.1.1

TheDeadRemain.dll

Decompiled 14 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace TheDeadRemain;

public sealed class CarcassHandle : IEquatable<CarcassHandle>
{
	public ZDOID Id { get; private set; }

	internal CarcassHandle(ZDOID id)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		Id = id;
	}

	public bool Equals(CarcassHandle other)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		if ((object)other != null)
		{
			return Id == other.Id;
		}
		return false;
	}

	public override bool Equals(object obj)
	{
		return Equals(obj as CarcassHandle);
	}

	public override int GetHashCode()
	{
		//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)
		return ((object)Id/*cast due to .constrained prefix*/).GetHashCode();
	}

	public static bool operator ==(CarcassHandle a, CarcassHandle b)
	{
		//IL_000f: 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)
		if ((object)a == b)
		{
			return true;
		}
		if ((object)a == null || (object)b == null)
		{
			return false;
		}
		return a.Id == b.Id;
	}

	public static bool operator !=(CarcassHandle a, CarcassHandle b)
	{
		return !(a == b);
	}

	public override string ToString()
	{
		//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)
		return "Carcass " + ((object)Id/*cast due to .constrained prefix*/).ToString();
	}
}
public static class DeadRemainApi
{
	public const int ApiVersion = 1;

	public const int StageFresh = 0;

	public const int StagePicked = 1;

	public const int StageBones = 2;

	public const int StageGone = 3;

	private const float DeathMatchSeconds = 10f;

	private static readonly List<ZDO> ZdoBuffer = new List<ZDO>();

	private static bool Ready
	{
		get
		{
			if (TdrConfig.Enabled != null && TdrConfig.Enabled.Value && (Object)(object)ZNet.instance != (Object)null && ZDOMan.instance != null)
			{
				return (Object)(object)ZNetScene.instance != (Object)null;
			}
			return false;
		}
	}

	public static event Action<CarcassHandle> CarcassCreated;

	public static event Action<CarcassHandle> CarcassStageChanged;

	public static CarcassHandle RegisterCarcass(Character c)
	{
		//IL_0021: 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_00a3: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!Ready || c == null)
			{
				return null;
			}
			if (CarcassFactory.TryGetRecent(c, out var id) && ZDOMan.instance.GetZDO(id) != null)
			{
				return new CarcassHandle(id);
			}
			if ((Object)(object)c == (Object)null)
			{
				return null;
			}
			ZNetView val = Reflect.NView(c);
			if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner())
			{
				return FindDeathCarcass(c, val);
			}
			if (c.IsDead() || c.GetHealth() <= 0f)
			{
				return null;
			}
			string reason;
			Carcass carcass = CarcassFactory.CreateFromPrefab(Utils.GetPrefabName(((Component)c).gameObject), ((Component)c).transform.position, ((Component)c).transform.rotation, c, out reason);
			if ((Object)(object)carcass == (Object)null)
			{
				Plugin.Verbose("The Dead Remain API: RegisterCarcass(" + ((Object)c).name + ") refused: " + reason);
			}
			return ((Object)(object)carcass != (Object)null) ? new CarcassHandle(carcass.Id) : null;
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("api-register", "The Dead Remain API: RegisterCarcass threw (" + ex.Message + ").");
			return null;
		}
	}

	public static CarcassHandle RegisterCarcass(string creaturePrefab, Vector3 pos, Quaternion rot)
	{
		//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_0043: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!Ready)
			{
				return null;
			}
			string reason;
			Carcass carcass = CarcassFactory.CreateFromPrefab(creaturePrefab, pos, rot, null, out reason);
			if ((Object)(object)carcass == (Object)null)
			{
				Plugin.Verbose("The Dead Remain API: RegisterCarcass(" + creaturePrefab + ") refused: " + reason);
			}
			return ((Object)(object)carcass != (Object)null) ? new CarcassHandle(carcass.Id) : null;
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("api-register-prefab", "The Dead Remain API: RegisterCarcass(prefab) threw (" + ex.Message + ").");
			return null;
		}
	}

	public static List<CarcassHandle> GetCarcassesInRange(Vector3 p, float r)
	{
		//IL_0024: 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)
		List<CarcassHandle> list = new List<CarcassHandle>();
		try
		{
			if (!Ready)
			{
				return list;
			}
			double nowDay = GameTime.NowDay;
			ZdoBuffer.Clear();
			CarcassRegistry.CarcassZdosInRange(p, r, ZdoBuffer);
			for (int i = 0; i < ZdoBuffer.Count; i++)
			{
				if (!(CarcassRegistry.PredictedProgress(ZdoBuffer[i], nowDay) >= 3f))
				{
					list.Add(new CarcassHandle(ZdoBuffer[i].m_uid));
				}
			}
			ZdoBuffer.Clear();
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("api-range", "The Dead Remain API: GetCarcassesInRange threw (" + ex.Message + ").");
		}
		return list;
	}

	public static CarcassHandle FindNearestCarcass(Vector3 p, float r)
	{
		//IL_001e: 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_005c: 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_009c: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!Ready)
			{
				return null;
			}
			double nowDay = GameTime.NowDay;
			ZdoBuffer.Clear();
			CarcassRegistry.CarcassZdosInRange(p, r, ZdoBuffer);
			ZDO val = null;
			float num = float.MaxValue;
			for (int i = 0; i < ZdoBuffer.Count; i++)
			{
				ZDO val2 = ZdoBuffer[i];
				if (!(CarcassRegistry.PredictedProgress(val2, nowDay) >= 3f))
				{
					Vector3 val3 = CarcassRegistry.CenterOf(val2) - p;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (!(sqrMagnitude >= num))
					{
						num = sqrMagnitude;
						val = val2;
					}
				}
			}
			ZdoBuffer.Clear();
			return (val != null) ? new CarcassHandle(val.m_uid) : null;
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("api-nearest", "The Dead Remain API: FindNearestCarcass threw (" + ex.Message + ").");
			return null;
		}
	}

	public static int GetStage(CarcassHandle h)
	{
		float num = ProgressOf(h);
		if (!(num < 0f))
		{
			return Mathf.Min(3, (int)Mathf.Floor(num));
		}
		return 3;
	}

	public static float GetScentStrength(CarcassHandle h)
	{
		float num = ProgressOf(h);
		if (num < 0f || num >= 2f)
		{
			return 0f;
		}
		if (num < 1f)
		{
			return Mathf.Lerp(1f, 0.6f, num);
		}
		return Mathf.Lerp(0.5f, 0.2f, num - 1f);
	}

	public static bool IsFeedingSlotFree(CarcassHandle h)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!Ready || h == null)
			{
				return false;
			}
			if (CarcassRegistry.TryGet(h.Id, out var carcass))
			{
				return FeedingSlots.IsSlotFree(carcass);
			}
			float num = ProgressOf(h);
			return num >= 0f && num < 2f;
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("api-slot", "The Dead Remain API: IsFeedingSlotFree threw (" + ex.Message + ").");
			return false;
		}
	}

	public static bool ClaimFeedingSlot(CarcassHandle h, Character c)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!Ready || h == null || (Object)(object)c == (Object)null)
			{
				return false;
			}
			Carcass carcass;
			return CarcassRegistry.TryGet(h.Id, out carcass) && FeedingSlots.Claim(carcass, c);
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("api-claim", "The Dead Remain API: ClaimFeedingSlot threw (" + ex.Message + ").");
			return false;
		}
	}

	public static void ReleaseFeedingSlot(CarcassHandle h, Character c)
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!(h == null) && !((Object)(object)c == (Object)null) && !((Object)(object)ZNet.instance == (Object)null))
			{
				FeedingSlots.Release(h.Id, c);
			}
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("api-release", "The Dead Remain API: ReleaseFeedingSlot threw (" + ex.Message + ").");
		}
	}

	public static bool TryGetCarcassCenter(CarcassHandle h, out Vector3 center)
	{
		//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_0023: 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_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_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)
		center = Vector3.zero;
		try
		{
			if (!Ready || h == null)
			{
				return false;
			}
			if (CarcassRegistry.TryGet(h.Id, out var carcass))
			{
				if (carcass.Removing)
				{
					return false;
				}
				center = carcass.Center;
				return true;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(h.Id);
			if (zDO == null || !CarcassRegistry.IsCarcassZdo(zDO))
			{
				return false;
			}
			if (CarcassRegistry.PredictedProgress(zDO, GameTime.NowDay) >= 3f)
			{
				return false;
			}
			center = CarcassRegistry.CenterOf(zDO);
			return true;
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("api-center", "The Dead Remain API: TryGetCarcassCenter threw (" + ex.Message + ").");
			return false;
		}
	}

	public static bool TieToCarcass(GameObject go, Vector3 near, float radius)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (!Ready || (Object)(object)go == (Object)null)
			{
				return false;
			}
			return TiedObjects.Tie(go, near, radius);
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("api-tie", "The Dead Remain API: TieToCarcass threw (" + ex.Message + ").");
			return false;
		}
	}

	public static bool TieToCarcassOf(GameObject go, GameObject source)
	{
		try
		{
			if (!Ready || (Object)(object)go == (Object)null || (Object)(object)source == (Object)null)
			{
				return false;
			}
			return TiedObjects.TieToSource(go, source);
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("api-tie-of", "The Dead Remain API: TieToCarcassOf threw (" + ex.Message + ").");
			return false;
		}
	}

	private static CarcassHandle FindDeathCarcass(Character c, ZNetView view)
	{
		//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_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: 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_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		string prefabName = Utils.GetPrefabName(((Component)c).gameObject);
		Vector3 position = ((Component)c).transform.position;
		long num = (((Object)(object)view != (Object)null && view.IsValid()) ? view.GetZDO().GetOwner() : 0);
		double nowDay = GameTime.NowDay;
		double num2 = GameTime.RealSecondsToDays(10.0);
		ZdoBuffer.Clear();
		CarcassRegistry.CarcassZdosInRange(position, Mathf.Max(4f, CarcassFactory.SizeOf(c)), ZdoBuffer);
		ZDO val = null;
		float num3 = float.MaxValue;
		for (int i = 0; i < ZdoBuffer.Count; i++)
		{
			ZDO val2 = ZdoBuffer[i];
			if (!(val2.GetString(ZdoKeys.Species, "") != prefabName) && (num == 0L || val2.GetOwner() == num) && !(Math.Abs(nowDay - (double)val2.GetFloat(ZdoKeys.DeathDay, -1000f)) > num2))
			{
				Vector3 val3 = CarcassRegistry.CenterOf(val2) - position;
				float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
				if (!(sqrMagnitude >= num3))
				{
					num3 = sqrMagnitude;
					val = val2;
				}
			}
		}
		ZdoBuffer.Clear();
		if (val == null)
		{
			return null;
		}
		return new CarcassHandle(val.m_uid);
	}

	private static float ProgressOf(CarcassHandle h)
	{
		//IL_001c: 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)
		try
		{
			if (!Ready || h == null)
			{
				return -1f;
			}
			if (CarcassRegistry.TryGet(h.Id, out var carcass))
			{
				return carcass.Removing ? (-1f) : carcass.Progress;
			}
			ZDO zDO = ZDOMan.instance.GetZDO(h.Id);
			if (zDO == null || !CarcassRegistry.IsCarcassZdo(zDO))
			{
				return -1f;
			}
			float num = CarcassRegistry.PredictedProgress(zDO, GameTime.NowDay);
			return (num >= 3f) ? (-1f) : num;
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("api-progress", "The Dead Remain API: reading a carcass threw (" + ex.Message + ").");
			return -1f;
		}
	}

	internal static void RaiseCreated(ZDOID id)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		Raise(DeadRemainApi.CarcassCreated, id, "CarcassCreated");
	}

	internal static void RaiseStageChanged(ZDOID id)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		Raise(DeadRemainApi.CarcassStageChanged, id, "CarcassStageChanged");
	}

	private static void Raise(Action<CarcassHandle> handlers, ZDOID id, string name)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		if (handlers == null)
		{
			return;
		}
		CarcassHandle obj = new CarcassHandle(id);
		Delegate[] invocationList = handlers.GetInvocationList();
		for (int i = 0; i < invocationList.Length; i++)
		{
			try
			{
				((Action<CarcassHandle>)invocationList[i])(obj);
			}
			catch (Exception ex)
			{
				Plugin.LogOnce("api-event-" + name + "-" + invocationList[i].Method.Name, "The Dead Remain API: a " + name + " handler (" + invocationList[i].Method.DeclaringType?.ToString() + "." + invocationList[i].Method.Name + ") threw (" + ex.Message + ").");
			}
		}
	}
}
internal enum BirdState
{
	Waiting,
	Arriving,
	Circling,
	Descending,
	Feeding,
	Ascending,
	Scatter,
	Leaving,
	Gone
}
internal sealed class Bird
{
	private const float Gravity = 9.81f;

	private const float CruiseSpeed = 8f;

	private const float ArriveSpeed = 11f;

	private const float GlideSpeed = 9.5f;

	private const float ApproachSpeed = 6.5f;

	private const float TouchdownSpeed = 1f;

	private const float ScatterSpeed = 10f;

	private const float LeaveSpeed = 11f;

	private const float ApproachRadius = 4.5f;

	private const float ApproachAngle = 0.75f;

	private const float ApproachHeight = 2.2f;

	private const float Clearance = 6f;

	private const float TreeAllowance = 20f;

	private const float MaxArriveDistance = 400f;

	private const float FlarePitch = 38f;

	private const float PeckSeconds = 0.38f;

	private const float HopSeconds = 0.32f;

	private const float HopHeight = 0.18f;

	private const float NoGround = -10000f;

	internal BirdState State;

	internal BirdView View;

	internal float Delay;

	internal Vector3 Pos;

	internal float Yaw;

	private float yawRate;

	private float speed;

	private float vy;

	private float pitch;

	private float roll;

	private float stateTime;

	private float groundY = -10000f;

	private float nextGround;

	private readonly float radiusOffset;

	private readonly float heightOffset;

	private readonly float speedFactor;

	private readonly float bobPhase;

	private readonly float bobRate;

	private readonly float breathePhase;

	private readonly float breatheRate;

	private readonly float noiseSeed;

	private readonly float sizeJitter;

	private readonly float animJitter;

	private bool flapping = true;

	private float flapLeft;

	private float animSpeed = 1f;

	private float nextDescent;

	private int segment;

	private float pathU;

	private float startSpeed;

	private Vector3 pathCenter;

	private float a0;

	private float aA;

	private float r0;

	private float rA;

	private float y0;

	private float yA;

	private Vector3 b0;

	private Vector3 b1;

	private Vector3 b2;

	private Vector3 b3;

	private float flare;

	internal Vector3 Spot;

	private float feedLeft;

	private float nextLook;

	private float lookYaw;

	private float nextPeck;

	private float peckTime = -1f;

	private float hopTime = -1f;

	private Vector3 hopFrom;

	private Vector3 hopTo;

	private Vector3 target;

	private float scatterWide;

	private Vector3 leaveDir;

	private float leaveY;

	internal bool IsDown
	{
		get
		{
			if (State != BirdState.Descending)
			{
				return State == BirdState.Feeding;
			}
			return true;
		}
	}

	internal Bird(Flock flock)
	{
		radiusOffset = flock.Range(-4f, 4f);
		heightOffset = flock.Range(-4f, 4f);
		speedFactor = flock.Range(0.9f, 1.1f);
		bobPhase = flock.Range(0f, 6.283f);
		bobRate = 6.283f / flock.Range(9f, 16f);
		breathePhase = flock.Range(0f, 6.283f);
		breatheRate = 6.283f / flock.Range(11f, 19f);
		noiseSeed = flock.Range(0f, 100f);
		sizeJitter = flock.Range(0.92f, 1.08f);
		animJitter = flock.Range(0.9f, 1.12f);
		flapLeft = flock.Range(0.2f, 2f);
	}

	private void SetState(BirdState state)
	{
		State = state;
		stateTime = 0f;
	}

	internal void PlaceOnCircle(Flock flock, float angle)
	{
		//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_0010: 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_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)
		Vector3 circleCentre = flock.CircleCentre;
		float num = CircleRadius(flock);
		Pos = new Vector3(circleCentre.x + Mathf.Cos(angle) * num, CircleY(flock), circleCentre.z + Mathf.Sin(angle) * num);
		Yaw = TangentYaw(flock, angle);
		speed = 8f * speedFactor;
		vy = 0f;
		yawRate = (float)(-flock.Dir) * (speed / num) * 57.29578f;
		SetState(BirdState.Circling);
		nextDescent = flock.Range(2f, 20f);
	}

	internal bool PlaceLanded(Flock flock, float angle)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: 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_0025: 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_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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)
		float num = flock.LandingRadius();
		Vector3 center = flock.Center;
		if (!flock.FindSpot(this, new Vector3(center.x + Mathf.Cos(angle) * num, center.y, center.z + Mathf.Sin(angle) * num), out var spot))
		{
			return false;
		}
		Spot = spot;
		Pos = spot;
		Yaw = YawTo(Spot, center) + flock.Range(-60f, 60f);
		Land(flock);
		feedLeft = flock.Range(2f, 15f);
		return true;
	}

	internal void BeginArriving(Flock flock)
	{
		//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_0030: 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_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_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: 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_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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_0099: 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_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		Vector3 center = flock.Center;
		float num = flock.ArrivalBearing + flock.Range(-0.7f, 0.7f);
		float distance = flock.Range(90f, 120f);
		float height = center.y + flock.BaseHeight + flock.Range(6f, 16f);
		Pos = ArrivalPoint(center, num, distance, height);
		if (!BirdFlocks.Unseen(Pos))
		{
			Vector3 val = ArrivalPoint(center, num + (float)Math.PI, distance, height);
			if (BirdFlocks.Unseen(val))
			{
				Pos = val;
			}
			else
			{
				float num2 = DistancePastView(center, num, distance);
				float num3 = DistancePastView(center, num + (float)Math.PI, distance);
				if (num3 < num2)
				{
					num += (float)Math.PI;
					num2 = num3;
				}
				Pos = ArrivalPoint(center, num, Mathf.Min(num2, 400f), height);
			}
		}
		Yaw = YawTo(Pos, center);
		speed = 11f * speedFactor;
		vy = 0f;
		yawRate = 0f;
		SetState(BirdState.Arriving);
	}

	private static Vector3 ArrivalPoint(Vector3 c, float bearing, float distance, float height)
	{
		//IL_0002: 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_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = default(Vector3);
		((Vector3)(ref val))..ctor(c.x + Mathf.Cos(bearing) * distance, height, c.z + Mathf.Sin(bearing) * distance);
		val.y = Mathf.Max(val.y, SolidHeight(val) + 6f + 8f);
		return val;
	}

	private static float DistancePastView(Vector3 c, float bearing, float distance)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: 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)
		Vector3 cameraPos = BirdFlocks.CameraPos;
		float num = cameraPos.x - c.x;
		float num2 = cameraPos.z - c.z;
		float num3 = num * Mathf.Cos(bearing) + num2 * Mathf.Sin(bearing);
		float num4 = num * num + num2 * num2 - num3 * num3;
		float unseenDistance = BirdFlocks.UnseenDistance;
		if (num4 >= unseenDistance * unseenDistance)
		{
			return distance;
		}
		return Mathf.Max(distance, num3 + Mathf.Sqrt(unseenDistance * unseenDistance - num4) + 1f);
	}

	internal void Update(Flock flock, float dt)
	{
		stateTime += dt;
		switch (State)
		{
		default:
			return;
		case BirdState.Waiting:
			Delay -= dt;
			if (Delay <= 0f)
			{
				BeginArriving(flock);
			}
			return;
		case BirdState.Arriving:
			UpdateArriving(flock, dt);
			break;
		case BirdState.Circling:
			UpdateCircling(flock, dt);
			break;
		case BirdState.Descending:
			UpdateDescending(flock, dt);
			break;
		case BirdState.Feeding:
			UpdateFeeding(flock, dt);
			return;
		case BirdState.Ascending:
			UpdateAscending(flock, dt);
			break;
		case BirdState.Scatter:
			UpdateScatter(flock, dt);
			break;
		case BirdState.Leaving:
			UpdateLeaving(flock, dt);
			break;
		}
		if (State != BirdState.Feeding)
		{
			Orient(flock, dt);
		}
	}

	internal void ApplyView(Flock flock)
	{
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: 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_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		if (View == null)
		{
			return;
		}
		View.SetScale(TdrConfig.BirdScale.Value * sizeJitter);
		if (State == BirdState.Feeding)
		{
			View.SetLanded(value: true);
			Vector3 val = Spot;
			if (hopTime >= 0f)
			{
				float num = Mathf.Clamp01(hopTime / 0.32f);
				val = Vector3.Lerp(hopFrom, hopTo, num) + Vector3.up * (0.72f * num * (1f - num));
			}
			float num2 = ((peckTime >= 0f) ? (Mathf.Sin(Mathf.Clamp01(peckTime / 0.38f) * (float)Math.PI) * 30f) : 0f);
			View.T.SetPositionAndRotation(val, Quaternion.Euler(num2, Yaw, 0f));
		}
		else
		{
			View.SetLanded(value: false);
			View.T.SetPositionAndRotation(Pos, Quaternion.Euler(pitch, Yaw, roll));
			View.SetFlapping(flapping);
			View.SetAnimSpeed(animSpeed * animJitter);
		}
	}

	private void UpdateArriving(Flock flock, float dt)
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		FlyCircle(flock, 11f * speedFactor, 3f, 3f, 3f, dt);
		Flap(flock, vy > 1.2f, dt);
		animSpeed = 1f;
		Vector3 val = Pos - flock.CircleCentre;
		val.y = 0f;
		if (Mathf.Abs(((Vector3)(ref val)).magnitude - CircleRadius(flock)) < 5f && Mathf.Abs(Pos.y - FlightY(flock)) < 5f)
		{
			SetState(BirdState.Circling);
			nextDescent = flock.Range(6f, 20f);
		}
	}

	private void UpdateCircling(Flock flock, float dt)
	{
		FlyCircle(flock, 8f * speedFactor, 3f, 3f, 2.5f, dt);
		Flap(flock, vy > 1.2f, dt);
		animSpeed = 1f;
		nextDescent -= dt;
		if (!(nextDescent > 0f) && (!flock.MayDescend() || !TryStartDescent(flock)))
		{
			nextDescent = flock.Range(3f, 9f);
		}
	}

	private void UpdateAscending(Flock flock, float dt)
	{
		float accel = ((stateTime < 0.4f) ? 2f : 3.5f);
		FlyCircle(flock, 8f * speedFactor, accel, 4.5f, 1.5f, dt);
		Flap(flock, force: true, dt);
		animSpeed = ((stateTime < 1.5f) ? 1.25f : 1f);
		if (stateTime > 2f && Mathf.Abs(Pos.y - FlightY(flock)) < 2.5f)
		{
			SetState(BirdState.Circling);
			animSpeed = 1f;
			nextDescent = flock.Range(6f, 20f);
		}
	}

	private void FlyCircle(Flock flock, float cruise, float accel, float climbMax, float sinkMax, float dt)
	{
		//IL_0009: 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_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_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_0051: 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_004a: 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_007f: 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_0093: 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_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		SampleGround(dt);
		Vector3 circleCentre = flock.CircleCentre;
		float num = CircleRadius(flock);
		float targetY = FlightY(flock);
		Vector3 val = Pos - circleCentre;
		val.y = 0f;
		float magnitude = ((Vector3)(ref val)).magnitude;
		Vector3 val2 = ((magnitude > 0.01f) ? (val / magnitude) : Vector3.right);
		Vector3 val3 = ((flock.Dir > 0) ? new Vector3(0f - val2.z, 0f, val2.x) : new Vector3(val2.z, 0f, 0f - val2.x));
		float num2 = Mathf.Clamp((magnitude - num) / 6f, -1.5f, 1.5f);
		Vector3 desired = val3 - val2 * num2;
		float num3 = 1f - Mathf.Clamp01(Mathf.Abs(magnitude - num) / 12f);
		float feedForward = (float)(-flock.Dir) * (speed / Mathf.Max(magnitude, 3f)) * 57.29578f * num3;
		SteerHeading(desired, feedForward, dt);
		speed = Mathf.MoveTowards(speed, cruise, accel * dt);
		SteerClimb(targetY, climbMax, sinkMax, dt);
		Integrate(dt);
	}

	private float CircleRadius(Flock flock)
	{
		return Mathf.Max(flock.BaseRadius + radiusOffset + 1.5f * Mathf.Sin(flock.Clock * breatheRate + breathePhase) + flock.AlarmBlend * (flock.BaseRadius * 0.6f + 4f), 3f + flock.Size);
	}

	private float CircleY(Flock flock)
	{
		return flock.Center.y + flock.BaseHeight + heightOffset + 1.8f * Mathf.Sin(flock.Clock * bobRate + bobPhase) + flock.AlarmBlend * 10f;
	}

	private float FlightY(Flock flock)
	{
		return Mathf.Max(CircleY(flock), groundY + 6f);
	}

	private static float TangentYaw(Flock flock, float angle)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: 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_0052: 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)
		Vector3 val = default(Vector3);
		((Vector3)(ref val))..ctor(Mathf.Cos(angle), 0f, Mathf.Sin(angle));
		Vector3 val2 = ((flock.Dir > 0) ? new Vector3(0f - val.z, 0f, val.x) : new Vector3(val.z, 0f, 0f - val.x));
		return Mathf.Atan2(val2.x, val2.z) * 57.29578f;
	}

	private bool TryStartDescent(Flock flock)
	{
		//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_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: 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_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_019d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_023c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_0250: Unknown result type (might be due to invalid IL or missing references)
		//IL_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_0255: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0260: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: Unknown result type (might be due to invalid IL or missing references)
		//IL_0284: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_028c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0301: Unknown result type (might be due to invalid IL or missing references)
		//IL_0306: Unknown result type (might be due to invalid IL or missing references)
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_030e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0314: Unknown result type (might be due to invalid IL or missing references)
		//IL_0316: Unknown result type (might be due to invalid IL or missing references)
		Vector3 center = flock.Center;
		Vector3 val = Pos - center;
		val.y = 0f;
		float num = Mathf.Max(((Vector3)(ref val)).magnitude, 3f);
		float num2 = Mathf.Atan2(val.z, val.x);
		float num3 = flock.Dir;
		float num4 = Mathf.Max(0f, Pos.y - (center.y + 2.2f));
		float num5 = Mathf.Clamp((float)Math.PI * (0.8f + num4 / 22f), (float)Math.PI * 3f / 4f, 6.9115043f);
		Vector3 near = default(Vector3);
		Vector3 near2 = default(Vector3);
		Vector3 val4 = default(Vector3);
		for (int i = 0; i < 6; i++)
		{
			float num6 = num5 * flock.Range(0.8f, 1.25f);
			float num7 = num2 + num3 * (num6 + 0.75f);
			float num8 = flock.LandingRadius();
			((Vector3)(ref near))..ctor(center.x + Mathf.Cos(num7) * num8, center.y, center.z + Mathf.Sin(num7) * num8);
			if (flock.FindSpot(this, near, out var spot))
			{
				pathCenter = center;
				a0 = num2;
				r0 = num;
				y0 = Pos.y;
				aA = num2 + num3 * num6;
				rA = num8 + 4.5f;
				yA = spot.y + 2.2f;
				((Vector3)(ref near2))..ctor(center.x + Mathf.Cos(aA) * rA, center.y, center.z + Mathf.Sin(aA) * rA);
				if (flock.GroundAt(near2, out var ground) && ground.y > yA - 1f)
				{
					yA = ground.y + 1.5f;
				}
				Vector3 val2 = spot - Vector3.up * flock.TouchdownDrop;
				Vector3 val3 = SpiralPoint(1f);
				((Vector3)(ref val4))..ctor(Mathf.Cos(aA), 0f, Mathf.Sin(aA));
				Vector3 val5 = ((num3 > 0f) ? new Vector3(0f - val4.z, 0f, val4.x) : new Vector3(val4.z, 0f, 0f - val4.x));
				Vector3 val6 = val2 - val3;
				val6.y = 0f;
				float num9 = Mathf.Max(((Vector3)(ref val6)).magnitude, 1f);
				b0 = val3;
				b1 = val3 + val5 * (num9 * 0.45f);
				Vector3 val7 = val2 - b1;
				val7.y = 0f;
				val7 = ((((Vector3)(ref val7)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref val7)).normalized : val5);
				b2 = val2 - val7 * (num9 * 0.3f) + Vector3.up * 0.5f;
				b3 = val2;
				Spot = spot;
				segment = 0;
				pathU = 0f;
				startSpeed = speed;
				flare = 0f;
				SetState(BirdState.Descending);
				return true;
			}
		}
		return false;
	}

	private void UpdateDescending(Flock flock, float dt)
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		float num;
		if (segment == 0)
		{
			num = Mathf.Lerp(startSpeed, 9.5f, Smooth01(pathU / 0.3f));
			num = Mathf.Lerp(num, 6.5f, Smooth01((pathU - 0.7f) / 0.3f));
		}
		else
		{
			num = Mathf.Lerp(6.5f, 1f, Smooth01(pathU));
		}
		Vector3 next = AdvancePath(Mathf.Max(num, 0.6f), dt);
		FollowPath(next, dt);
		if (segment == 0)
		{
			flare = 0f;
			flapping = false;
			animSpeed = 1f;
			if (pathU >= 1f)
			{
				segment = 1;
				pathU = 0f;
			}
		}
		else
		{
			flare = Smooth01((pathU - 0.35f) / 0.45f) * (1f - 0.6f * Smooth01((pathU - 0.85f) / 0.15f));
			animSpeed = ((flapping = pathU > 0.4f) ? 1.25f : 1f);
			if (pathU >= 1f)
			{
				Land(flock);
			}
		}
	}

	private Vector3 PathPoint(float u)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_000a: Unknown result type (might be due to invalid IL or missing references)
		if (segment == 0)
		{
			return SpiralPoint(u);
		}
		float num = 1f - u;
		return num * num * num * b0 + 3f * num * num * u * b1 + 3f * num * u * u * b2 + u * u * u * b3;
	}

	private Vector3 SpiralPoint(float u)
	{
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		float num = Smooth01(u);
		float num2 = Mathf.Lerp(a0, aA, u);
		float num3 = Mathf.Lerp(r0, rA, num);
		return new Vector3(pathCenter.x + Mathf.Cos(num2) * num3, Mathf.Lerp(y0, yA, num), pathCenter.z + Mathf.Sin(num2) * num3);
	}

	private Vector3 AdvancePath(float metresPerSecond, float dt)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: 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)
		float num = Mathf.Max(0f, pathU - 0.01f);
		float num2 = Mathf.Min(1f, pathU + 0.01f);
		Vector3 val = PathPoint(num2) - PathPoint(num);
		float num3 = ((Vector3)(ref val)).magnitude / Mathf.Max(num2 - num, 0.0001f);
		pathU = Mathf.Min(1f, pathU + metresPerSecond * dt / Mathf.Max(num3, 0.05f));
		return PathPoint(pathU);
	}

	private void FollowPath(Vector3 next, float dt)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: 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_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: 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_006c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = next - Pos;
		Pos = next;
		if (!(dt <= 1E-05f))
		{
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(val.x, 0f, val.z);
			float magnitude = ((Vector3)(ref val2)).magnitude;
			float num = 1f - Mathf.Exp(-10f * dt);
			speed = Mathf.Lerp(speed, magnitude / dt, num);
			vy = Mathf.Lerp(vy, val.y / dt, num);
			if (!(magnitude < 0.0001f))
			{
				float yaw = Yaw;
				Yaw = Mathf.LerpAngle(Yaw, Mathf.Atan2(val2.x, val2.z) * 57.29578f, num);
				yawRate = Mathf.Lerp(yawRate, Mathf.DeltaAngle(yaw, Yaw) / dt, 1f - Mathf.Exp(-6f * dt));
			}
		}
	}

	private void Land(Flock flock)
	{
		//IL_0009: 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_006d: 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)
		SetState(BirdState.Feeding);
		Pos = Spot;
		speed = 0f;
		vy = 0f;
		yawRate = 0f;
		pitch = 0f;
		roll = 0f;
		flare = 0f;
		peckTime = -1f;
		hopTime = -1f;
		lookYaw = YawTo(Spot, flock.Center) + flock.Range(-45f, 45f);
		feedLeft = flock.Range(5f, 15f);
		nextLook = flock.Range(0.6f, 2f);
		nextPeck = flock.Range(0.3f, 1.2f);
	}

	private void UpdateFeeding(Flock flock, float dt)
	{
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		feedLeft -= dt;
		if (feedLeft <= 0f && hopTime < 0f)
		{
			TakeOff(flock, panic: false);
			SetState(BirdState.Ascending);
			return;
		}
		Yaw = Mathf.MoveTowardsAngle(Yaw, lookYaw, 160f * dt);
		if (hopTime >= 0f)
		{
			hopTime += dt;
			if (hopTime >= 0.32f)
			{
				hopTime = -1f;
				Spot = hopTo;
			}
		}
		if (peckTime >= 0f)
		{
			peckTime += dt;
			if (peckTime >= 0.38f)
			{
				peckTime = -1f;
			}
		}
		else if (hopTime < 0f)
		{
			nextPeck -= dt;
			if (nextPeck <= 0f)
			{
				peckTime = 0f;
				nextPeck = flock.Range(0.4f, 1.8f);
			}
		}
		nextLook -= dt;
		if (!(nextLook > 0f))
		{
			nextLook = flock.Range(0.8f, 2.6f);
			lookYaw = YawTo(Spot, flock.Center) + flock.Range(-70f, 70f);
			if (peckTime < 0f && hopTime < 0f && flock.Range(0f, 1f) < 0.3f)
			{
				TryHop(flock);
			}
		}
	}

	private void TryHop(Flock flock)
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_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_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_0064: 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_0096: 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_00bc: 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_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: 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)
		float num = flock.Range(0f, 360f);
		float num2 = flock.Range(0.25f, 0.55f);
		for (int i = 0; i < 2; i++)
		{
			Vector3 val = Quaternion.Euler(0f, num + (float)i * 180f, 0f) * Vector3.forward * num2;
			Vector3 val2 = Spot + val;
			float num3 = Utils.DistanceXZ(val2, flock.Center);
			if (!(num3 < flock.MinLandRadius) && !(num3 > flock.MaxLandRadius + 0.6f) && flock.GroundAt(val2, out var ground) && !(Mathf.Abs(ground.y - Spot.y) > 0.6f))
			{
				hopFrom = Spot;
				hopTo = ground;
				hopTime = 0f;
				lookYaw = Mathf.Atan2(val.x, val.z) * 57.29578f;
				break;
			}
		}
	}

	private void TakeOff(Flock flock, bool panic)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: 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_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		if (hopTime >= 0f)
		{
			Spot = hopTo;
		}
		hopTime = -1f;
		peckTime = -1f;
		Pos = Spot - Vector3.up * flock.TouchdownDrop;
		speed = (panic ? 1.5f : 0.8f);
		vy = (panic ? 5f : 3f);
		yawRate = 0f;
		roll = 0f;
		pitch = -20f;
		flapping = true;
		flapLeft = flock.Range(1f, 1.6f);
		groundY = -10000f;
		nextGround = 0f;
	}

	internal void BeginScatter(Flock flock, Vector3 from)
	{
		//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_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: 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_007b: 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_00b8: 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_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: 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_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: 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_0120: 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_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		if (State == BirdState.Feeding)
		{
			TakeOff(flock, panic: true);
		}
		else
		{
			vy = Mathf.Max(vy, 2.5f);
		}
		Vector3 center = flock.Center;
		Vector3 val = Pos - center;
		val.y = 0f;
		if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
		{
			val = Quaternion.Euler(0f, flock.Range(0f, 360f), 0f) * Vector3.forward;
		}
		Vector3 val2 = Pos - from;
		val2.y = 0f;
		Vector3 val3 = ((Vector3)(ref val)).normalized + ((((Vector3)(ref val2)).sqrMagnitude > 0.01f) ? (((Vector3)(ref val2)).normalized * 0.8f) : Vector3.zero);
		if (((Vector3)(ref val3)).sqrMagnitude < 0.01f)
		{
			val3 = val;
		}
		((Vector3)(ref val3)).Normalize();
		scatterWide = flock.BaseRadius * 1.6f + 6f + flock.Range(0f, 6f);
		target = center + val3 * scatterWide;
		target.y = center.y + flock.BaseHeight + 10f + heightOffset;
		flare = 0f;
		SetState(BirdState.Scatter);
	}

	private void UpdateScatter(Flock flock, float dt)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		SampleGround(dt);
		SteerHeading(target - Pos, 0f, dt);
		speed = Mathf.MoveTowards(speed, 10f * speedFactor, 6f * dt);
		SteerClimb(Mathf.Max(target.y, groundY + 6f), 7f, 2f, dt);
		Integrate(dt);
		flapping = true;
		animSpeed = 1.35f;
		if (stateTime > 7f || (stateTime > 2f && (Pos.y > target.y - 4f || Utils.DistanceXZ(Pos, flock.Center) > scatterWide)))
		{
			SetState(BirdState.Circling);
			animSpeed = 1f;
			nextDescent = flock.Range(6f, 20f);
		}
	}

	internal void BeginLeaving(Flock flock, float bearing)
	{
		//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)
		if (State == BirdState.Waiting || State == BirdState.Gone)
		{
			SetState(BirdState.Gone);
			return;
		}
		if (State == BirdState.Feeding)
		{
			TakeOff(flock, panic: false);
		}
		float num = bearing + flock.Range(-0.9f, 0.9f);
		leaveDir = new Vector3(Mathf.Cos(num), 0f, Mathf.Sin(num));
		leaveY = flock.Center.y + flock.BaseHeight + flock.Range(25f, 40f);
		flare = 0f;
		animSpeed = 1f;
		SetState(BirdState.Leaving);
	}

	internal void Vanish()
	{
		SetState(BirdState.Gone);
	}

	internal void Rejoin(Flock flock)
	{
		if (State == BirdState.Leaving)
		{
			SetState(BirdState.Circling);
			nextDescent = flock.Range(6f, 20f);
		}
	}

	private void UpdateLeaving(Flock flock, float dt)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		SampleGround(dt);
		SteerHeading(leaveDir, 0f, dt);
		speed = Mathf.MoveTowards(speed, 11f * speedFactor, 3f * dt);
		SteerClimb(Mathf.Max(leaveY, groundY + 6f), 4f, 2f, dt);
		Integrate(dt);
		Flap(flock, vy > 1.2f || stateTime < 1.5f, dt);
		if (stateTime > (2f * TdrConfig.BirdsVisibleDistance.Value + 120f) / 11f)
		{
			SetState(BirdState.Gone);
		}
	}

	private void SteerHeading(Vector3 desired, float feedForward, float dt)
	{
		//IL_001b: 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)
		desired.y = 0f;
		if (!(((Vector3)(ref desired)).sqrMagnitude < 1E-06f))
		{
			float num = Mathf.Atan2(desired.x, desired.z) * 57.29578f;
			float num2 = Mathf.Lerp(300f, 75f, Mathf.Clamp01(speed / 8f));
			float num3 = Mathf.Clamp(feedForward + Mathf.DeltaAngle(Yaw, num) * 2.5f, 0f - num2, num2);
			yawRate = Mathf.Lerp(yawRate, num3, 1f - Mathf.Exp(-4f * dt));
			Yaw = Mathf.Repeat(Yaw + yawRate * dt, 360f);
		}
	}

	private void SteerClimb(float targetY, float climbMax, float sinkMax, float dt)
	{
		float num = Mathf.Clamp((targetY - Pos.y) * 0.7f, 0f - sinkMax, climbMax);
		vy = Mathf.Lerp(vy, num, 1f - Mathf.Exp(-2.5f * dt));
	}

	private void Integrate(float dt)
	{
		//IL_000f: 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)
		float num = Yaw * ((float)Math.PI / 180f);
		Pos += new Vector3(Mathf.Sin(num) * speed * dt, vy * dt, Mathf.Cos(num) * speed * dt);
	}

	private void SampleGround(float dt)
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		nextGround -= dt;
		if (!(nextGround > 0f))
		{
			nextGround = 0.4f;
			groundY = SolidHeight(Pos);
		}
	}

	private static float SolidHeight(Vector3 point)
	{
		//IL_0012: 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_0035: Unknown result type (might be due to invalid IL or missing references)
		float result = default(float);
		if ((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetSolidHeight(point, ref result, 1000))
		{
			return result;
		}
		if (WorldGenerator.instance != null)
		{
			return WorldGenerator.instance.GetHeight(point.x, point.z) + 20f;
		}
		return -10000f;
	}

	private void Flap(Flock flock, bool force, float dt)
	{
		flapLeft -= dt;
		if (force)
		{
			flapping = true;
			if (flapLeft < 0.3f)
			{
				flapLeft = 0.3f;
			}
		}
		else if (!(flapLeft > 0f))
		{
			flapping = !flapping;
			flapLeft = (flapping ? flock.Kind.FlapSeconds : flock.Kind.SailSeconds) * flock.Range(0.75f, 1.3f);
		}
	}

	private void Orient(Flock flock, float dt)
	{
		float num = (0f - Mathf.Atan(speed * yawRate * ((float)Math.PI / 180f) / 9.81f)) * 57.29578f;
		num = Mathf.Clamp(num, -55f, 55f);
		float num2 = (0f - Mathf.Atan2(vy, Mathf.Max(speed, 1f))) * 57.29578f * 0.8f;
		num2 = Mathf.Clamp(num2, -55f, 45f) * (1f - flare) - flare * 38f;
		float num3 = flock.Clock * 0.35f;
		num += (Mathf.PerlinNoise(noiseSeed, num3) - 0.5f) * 10f;
		num2 += (Mathf.PerlinNoise(num3, noiseSeed) - 0.5f) * 5f;
		float num4 = 1f - Mathf.Exp(-3.5f * dt);
		roll = Mathf.Lerp(roll, num, num4);
		pitch = Mathf.Lerp(pitch, num2, num4);
	}

	private static float YawTo(Vector3 from, Vector3 to)
	{
		//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_000d: 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)
		return Mathf.Atan2(to.x - from.x, to.z - from.z) * 57.29578f;
	}

	private static float Smooth01(float x)
	{
		x = Mathf.Clamp01(x);
		return x * x * (3f - 2f * x);
	}
}
internal static class BirdFlocks
{
	private const int MaxFlocks = 40;

	private const float MaintainSeconds = 0.5f;

	private const float HideMargin = 10f;

	private const float FreshArrivalSeconds = 180f;

	private const float ArrivalWindowSeconds = 90f;

	private const float NightGraceSeconds = 5f;

	private const float WaterRecheckSeconds = 20f;

	private const float ClusterRadius = 15f;

	private const float UnseenMargin = 20f;

	private const float OffScreenMinDistance = 60f;

	private const float ScreenMargin = 1.15f;

	private static readonly List<Flock> Flocks = new List<Flock>();

	private static readonly Dictionary<ZDOID, Flock> ById = new Dictionary<ZDOID, Flock>();

	private static readonly Dictionary<ZDOID, float> WetUntil = new Dictionary<ZDOID, float>();

	private static readonly List<ZDOID> Stale = new List<ZDOID>();

	private static bool hooked;

	private static bool allowedKnown;

	private static bool allowed;

	private static float allowedSince = -1000f;

	private static float darkFor;

	private static float envSeen = -1f;

	private static float nextMaintain;

	private static Vector3 cameraPos;

	private static bool haveCamera;

	private static Quaternion cameraToLocal = Quaternion.identity;

	private static float tanHalfWidth = 1f;

	private static float tanHalfHeight = 1f;

	internal static bool HaveCamera => haveCamera;

	internal static Vector3 CameraPos => cameraPos;

	internal static float UnseenDistance => TdrConfig.BirdsVisibleDistance.Value + 20f;

	internal static bool Unseen(Vector3 point)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: 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_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: 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_0081: 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)
		if (!haveCamera)
		{
			return true;
		}
		Vector3 val = point - cameraPos;
		float unseenDistance = UnseenDistance;
		if (val.x * val.x + val.z * val.z >= unseenDistance * unseenDistance)
		{
			return true;
		}
		if (((Vector3)(ref val)).sqrMagnitude < 3600f)
		{
			return false;
		}
		Vector3 val2 = cameraToLocal * val;
		if (val2.z <= 0f)
		{
			return true;
		}
		if (!(Mathf.Abs(val2.x) > val2.z * tanHalfWidth))
		{
			return Mathf.Abs(val2.y) > val2.z * tanHalfHeight;
		}
		return true;
	}

	internal static void Tick()
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0131: 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_0185: Unknown result type (might be due to invalid IL or missing references)
		if (CarcassVisuals.Headless)
		{
			return;
		}
		Hook();
		float time = Time.time;
		float dt = Mathf.Min(Time.deltaTime, 0.1f);
		UpdateAllowed(time, dt);
		Camera mainCamera = Utils.GetMainCamera();
		haveCamera = (Object)(object)mainCamera != (Object)null;
		if (haveCamera)
		{
			Transform transform = ((Component)mainCamera).transform;
			cameraPos = transform.position;
			cameraToLocal = Quaternion.Inverse(transform.rotation);
			tanHalfHeight = Mathf.Tan(mainCamera.fieldOfView * 0.5f * ((float)Math.PI / 180f)) * 1.15f;
			tanHalfWidth = tanHalfHeight * mainCamera.aspect;
		}
		if (time >= nextMaintain)
		{
			nextMaintain = time + 0.5f;
			Maintain(time);
		}
		if (Flocks.Count == 0)
		{
			return;
		}
		float value = TdrConfig.BirdsVisibleDistance.Value;
		for (int num = Flocks.Count - 1; num >= 0; num--)
		{
			if (num >= Flocks.Count)
			{
				continue;
			}
			Flock flock = Flocks[num];
			bool flag = haveCamera && ((!flock.Leaving || !flock.Visible) ? flock.WithinView(cameraPos, value + (flock.Visible ? 10f : 0f)) : flock.AnyBirdWithin(cameraPos, value + 40f));
			if (flag != flock.Visible)
			{
				flock.SetVisible(flag);
			}
			if (!flag)
			{
				if (flock.Leaving)
				{
					RemoveAt(num);
				}
				continue;
			}
			try
			{
				flock.Update(dt, cameraPos, value);
			}
			catch (Exception ex)
			{
				Plugin.LogOnce("bird-flock", "The Dead Remain: a bird flock threw (" + ex.GetType().Name + ": " + ex.Message + "); that flock is removed.\n" + ex.StackTrace);
				RemoveAt(num);
				continue;
			}
			if (flock.Finished)
			{
				RemoveAt(num);
			}
		}
	}

	internal static void ClearAll()
	{
		for (int i = 0; i < Flocks.Count; i++)
		{
			Flocks[i].ReleaseAll();
		}
		Flocks.Clear();
		ById.Clear();
		WetUntil.Clear();
		BirdKinds.ClearAll();
		allowedKnown = false;
		allowed = false;
		allowedSince = -1000f;
		darkFor = 0f;
		envSeen = -1f;
		nextMaintain = 0f;
		haveCamera = false;
	}

	internal static int LandedBirdCount(Carcass carcass)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		if (carcass == null)
		{
			return 0;
		}
		if (!ById.TryGetValue(carcass.Id, out var value) || !value.Visible || value.Leaving)
		{
			return 0;
		}
		return value.LandedCount;
	}

	internal static string StatusLine()
	{
		int num = 0;
		int num2 = 0;
		for (int i = 0; i < Flocks.Count; i++)
		{
			if (Flocks[i].Visible)
			{
				num++;
				num2 += Flocks[i].LandedCount;
			}
		}
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.Append("flocks ").Append(Flocks.Count).Append(" (")
			.Append(num)
			.Append(" shown), birds ")
			.Append(BirdKinds.LiveCount)
			.Append(", feeding ")
			.Append(num2)
			.Append(allowed ? "" : ", birds away (night or off)");
		return stringBuilder.ToString();
	}

	private static void Maintain(float now)
	{
		//IL_0084: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
		for (int i = 0; i < Flocks.Count; i++)
		{
			Flock flock = Flocks[i];
			if (!flock.Leaving && (!allowed || !StillWanted(flock.Carcass)))
			{
				LeaveFlock(flock, allowed ? "carcass" : "night");
			}
		}
		if (!allowed)
		{
			return;
		}
		IReadOnlyList<Carcass> loaded = CarcassRegistry.Loaded;
		for (int j = 0; j < loaded.Count; j++)
		{
			Carcass carcass = loaded[j];
			if (!StillWanted(carcass))
			{
				continue;
			}
			if (ById.TryGetValue(carcass.Id, out var value))
			{
				if (value.Leaving)
				{
					value.Rejoin(carcass);
				}
				else
				{
					value.Carcass = carcass;
				}
			}
			else if (!IsWet(carcass, now) && !CoveredByFlock(carcass.Center) && (Flocks.Count < 40 || MakeRoom(carcass.Center)))
			{
				Create(carcass, now);
			}
		}
		if (WetUntil.Count > 64)
		{
			PruneWet(now);
		}
	}

	private static bool CoveredByFlock(Vector3 center)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		float num = 225f;
		for (int i = 0; i < Flocks.Count; i++)
		{
			if (!Flocks[i].Leaving)
			{
				Vector3 val = Flocks[i].Center - center;
				if (((Vector3)(ref val)).sqrMagnitude < num)
				{
					return true;
				}
			}
		}
		return false;
	}

	private static bool StillWanted(Carcass carcass)
	{
		if ((Object)(object)carcass != (Object)null && carcass.IsValid && !carcass.Removing && carcass.Settled)
		{
			return carcass.Stage < 2;
		}
		return false;
	}

	private static void Create(Carcass carcass, float now)
	{
		//IL_000c: 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_00b1: 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)
		BirdKind birdKind = BirdKinds.For(carcass);
		if (birdKind != null)
		{
			uint num = Hash(carcass.Id);
			int count = Mathf.Clamp(TdrConfig.BirdsPerFlock.Value + (int)(num % 3) - 1, 1, 13);
			bool flag = Arrives(carcass, now);
			Flock flock = new Flock(carcass, birdKind, num >> 2, count, flag);
			Flocks.Add(flock);
			ById[carcass.Id] = flock;
			if (Plugin.LogEvents)
			{
				Plugin.Event("flock " + birdKind.Name + " x" + count + " over " + carcass.Species + " " + ((object)carcass.Id/*cast due to .constrained prefix*/).ToString() + (flag ? " (arriving)" : " (already there)"));
			}
		}
	}

	private static bool Arrives(Carcass carcass, float now)
	{
		if (now - allowedSince < 90f)
		{
			return true;
		}
		return GameTime.DaysToRealSeconds(GameTime.NowDay - (double)carcass.DeathDay) < 180.0;
	}

	private static bool MakeRoom(Vector3 candidate)
	{
		//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_0016: 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_004f: Unknown result type (might be due to invalid IL or missing references)
		if (!haveCamera)
		{
			return false;
		}
		int num = -1;
		Vector3 val = candidate - cameraPos;
		float num2 = ((Vector3)(ref val)).sqrMagnitude;
		for (int i = 0; i < Flocks.Count; i++)
		{
			if (!Flocks[i].Visible)
			{
				val = Flocks[i].Center - cameraPos;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (!(sqrMagnitude <= num2))
				{
					num2 = sqrMagnitude;
					num = i;
				}
			}
		}
		if (num < 0)
		{
			return false;
		}
		RemoveAt(num);
		return true;
	}

	private static void LeaveFlock(Flock flock, string reason)
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		if (!flock.Leaving)
		{
			flock.Leave();
			if (Plugin.LogEvents)
			{
				Plugin.Event("flock leaves " + flock.SpeciesName + " " + ((object)flock.Id/*cast due to .constrained prefix*/).ToString() + " (" + reason + ")");
			}
		}
	}

	private static void RemoveAt(int index)
	{
		//IL_0018: 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)
		Flock flock = Flocks[index];
		flock.ReleaseAll();
		if (ById.TryGetValue(flock.Id, out var value) && value == flock)
		{
			ById.Remove(flock.Id);
		}
		Flocks.RemoveAt(index);
	}

	private static bool IsWet(Carcass carcass, float now)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: 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_0042: Unknown result type (might be due to invalid IL or missing references)
		if (WetUntil.TryGetValue(carcass.Id, out var value) && now < value)
		{
			return true;
		}
		Vector3 center = carcass.Center;
		if (Floating.GetLiquidLevel(center, 1f, (LiquidType)10) <= center.y + 0.25f)
		{
			WetUntil.Remove(carcass.Id);
			return false;
		}
		WetUntil[carcass.Id] = now + 20f;
		return true;
	}

	private static void PruneWet(float now)
	{
		//IL_0030: 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)
		Stale.Clear();
		foreach (KeyValuePair<ZDOID, float> item in WetUntil)
		{
			if (now >= item.Value)
			{
				Stale.Add(item.Key);
			}
		}
		for (int i = 0; i < Stale.Count; i++)
		{
			WetUntil.Remove(Stale[i]);
		}
		Stale.Clear();
	}

	private static void UpdateAllowed(float now, float dt)
	{
		if ((Object)(object)EnvMan.instance == (Object)null)
		{
			envSeen = -1f;
			return;
		}
		if (envSeen < 0f)
		{
			envSeen = now;
		}
		if (now - envSeen < 1f)
		{
			return;
		}
		bool value = TdrConfig.EnableBirds.Value;
		bool flag = value && (TdrConfig.BirdsAtNight.Value || EnvMan.IsDaylight());
		if (!allowedKnown)
		{
			allowedKnown = true;
			allowed = flag;
			allowedSince = -1000f;
			darkFor = 0f;
		}
		else if (flag)
		{
			darkFor = 0f;
			if (!allowed)
			{
				allowed = true;
				allowedSince = now;
				nextMaintain = 0f;
			}
		}
		else
		{
			darkFor += dt;
			if (allowed && (!value || darkFor >= 5f))
			{
				allowed = false;
				nextMaintain = 0f;
			}
		}
	}

	private static void Hook()
	{
		if (!hooked)
		{
			hooked = true;
			CarcassEvents.Loaded += OnLoaded;
			CarcassEvents.Unloaded += OnUnloaded;
			CarcassEvents.StageChanged += OnStageChanged;
		}
	}

	private static void OnLoaded(Carcass carcass)
	{
		nextMaintain = 0f;
	}

	private static void OnUnloaded(Carcass carcass)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		if (carcass != null && ById.TryGetValue(carcass.Id, out var value) && value.Carcass == carcass)
		{
			value.Carcass = null;
			LeaveFlock(value, "unloaded");
		}
	}

	private static void OnStageChanged(Carcass carcass)
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		if (carcass != null && carcass.Stage >= 2 && ById.TryGetValue(carcass.Id, out var value))
		{
			LeaveFlock(value, Stages.Name(carcass.Stage));
		}
	}

	private unsafe static uint Hash(ZDOID id)
	{
		int hashCode = ((object)(*(ZDOID*)(&id))/*cast due to .constrained prefix*/).GetHashCode();
		int num = (hashCode ^ (hashCode >>> 16)) * 2146121005;
		int num2 = (num ^ (num >>> 15)) * -2073254261;
		return (uint)(num2 ^ (num2 >>> 16));
	}
}
internal sealed class BirdView
{
	internal BirdKind Kind;

	internal GameObject Root;

	internal Transform T;

	internal GameObject Fly;

	internal GameObject Land;

	internal Animator Animator;

	private bool landed;

	private int flapping = -1;

	private float animSpeed = -1f;

	private float scale = -1f;

	internal void Reset()
	{
		landed = false;
		flapping = -1;
		animSpeed = -1f;
		scale = -1f;
		if ((Object)(object)Fly != (Object)null)
		{
			Fly.SetActive(true);
		}
		if ((Object)(object)Land != (Object)null)
		{
			Land.SetActive(false);
		}
	}

	internal void SetLanded(bool value)
	{
		if (landed == value)
		{
			return;
		}
		landed = value;
		if (!((Object)(object)Land == (Object)null))
		{
			Land.SetActive(value);
			if ((Object)(object)Fly != (Object)null)
			{
				Fly.SetActive(!value);
			}
			if (!value)
			{
				flapping = -1;
				animSpeed = -1f;
			}
		}
	}

	internal void SetFlapping(bool value)
	{
		int num = (value ? 1 : 0);
		if (flapping != num && !landed && !((Object)(object)Animator == (Object)null) && BirdKinds.HasFlapping(Kind, Animator))
		{
			flapping = num;
			Animator.SetBool(BirdKinds.FlappingHash, value);
		}
	}

	internal void SetAnimSpeed(float value)
	{
		if (!((Object)(object)Animator == (Object)null) && !landed && !(Mathf.Abs(animSpeed - value) < 0.01f))
		{
			animSpeed = value;
			Animator.speed = value;
		}
	}

	internal void SetScale(float value)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		if (!(Mathf.Abs(scale - value) < 0.001f))
		{
			scale = value;
			T.localScale = new Vector3(value, value, value);
		}
	}
}
internal sealed class BirdKind
{
	internal string Name;

	internal GameObject FlyTemplate;

	internal GameObject LandTemplate;

	internal EffectList Caw;

	internal float FlapSeconds = 2f;

	internal float SailSeconds = 1.5f;

	internal float FlyLift;

	internal int ReadyFrame;

	internal int FlapParam = -1;

	internal readonly Stack<BirdView> Free = new Stack<BirdView>();
}
internal static class BirdKinds
{
	internal const string Crow = "Crow";

	internal const string Seagull = "Seagal";

	internal const string AshCrow = "AshCrow";

	internal static readonly int FlappingHash = Animator.StringToHash("flapping");

	private static readonly Dictionary<string, BirdKind> Kinds = new Dictionary<string, BirdKind>();

	private static readonly List<Component> ComponentBuffer = new List<Component>();

	private static readonly List<BirdView> Live = new List<BirdView>();

	private static GameObject holder;

	private static GameObject root;

	internal static int LiveCount => Live.Count;

	internal static float WaterLevel
	{
		get
		{
			if (!((Object)(object)ZoneSystem.instance != (Object)null))
			{
				return 30f;
			}
			return ZoneSystem.instance.m_waterLevel;
		}
	}

	internal static BirdKind For(Carcass carcass)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000e: Invalid comparison between Unknown and I4
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Invalid comparison between Unknown and I4
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Invalid comparison between Unknown and I4
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		string text = "Crow";
		if ((int)carcass.Biome == 32)
		{
			text = "AshCrow";
		}
		else if ((int)carcass.Biome == 256 || ((int)carcass.Biome != 2 && carcass.Center.y < WaterLevel + 2f))
		{
			text = "Seagal";
		}
		BirdKind birdKind = Get(text);
		if (birdKind == null && text != "Crow")
		{
			birdKind = Get("Crow");
		}
		return birdKind;
	}

	internal static bool IsReady(BirdKind kind)
	{
		if (kind != null)
		{
			return Time.frameCount >= kind.ReadyFrame;
		}
		return false;
	}

	private static BirdKind Get(string name)
	{
		if (Kinds.TryGetValue(name, out var value))
		{
			return value;
		}
		if ((Object)(object)ZNetScene.instance == (Object)null)
		{
			return null;
		}
		try
		{
			value = Build(name);
		}
		catch (Exception ex)
		{
			value = null;
			Plugin.LogOnce("bird-build-" + name, "The Dead Remain: copying the " + name + " models threw (" + ex.Message + ").");
		}
		Kinds[name] = value;
		if (value == null)
		{
			Plugin.LogOnce("bird-kind-" + name, "The Dead Remain: bird prefab '" + name + "' is missing or has no models; no " + name + " flocks.");
		}
		return value;
	}

	private static BirdKind Build(string name)
	{
		//IL_00d6: 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_0053: Expected O, but got Unknown
		GameObject prefab = ZNetScene.instance.GetPrefab(name);
		if ((Object)(object)prefab == (Object)null)
		{
			return null;
		}
		RandomFlyingBird component = prefab.GetComponent<RandomFlyingBird>();
		if ((Object)(object)component == (Object)null || (Object)(object)component.m_flyingModel == (Object)null)
		{
			return null;
		}
		if ((Object)(object)holder == (Object)null)
		{
			holder = new GameObject("TDR_BirdTemplates");
			holder.SetActive(false);
		}
		BirdKind birdKind = new BirdKind
		{
			Name = name,
			Caw = component.m_randomNoise,
			FlapSeconds = Mathf.Max(0.3f, component.m_flapDuration),
			SailSeconds = Mathf.Max(0.3f, component.m_sailDuration)
		};
		birdKind.FlyTemplate = Template(component.m_flyingModel, prefab.transform, name + "_flying");
		birdKind.FlyLift = Mathf.Max(0f, birdKind.FlyTemplate.transform.localPosition.y);
		if (!component.m_singleModel && (Object)(object)component.m_landedModel != (Object)null)
		{
			birdKind.LandTemplate = Template(component.m_landedModel, prefab.transform, name + "_landed");
		}
		birdKind.ReadyFrame = Time.frameCount + 2;
		Plugin.Verbose("The Dead Remain: bird models copied from " + name + " (landed model " + ((Object)(object)birdKind.LandTemplate != (Object)null) + ").");
		return birdKind;
	}

	private static GameObject Template(GameObject model, Transform prefabRoot, string label)
	{
		//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_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_0044: 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_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_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0072: 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_0083: 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_0094: Unknown result type (might be due to invalid IL or missing references)
		GameObject obj = Object.Instantiate<GameObject>(model, holder.transform, false);
		((Object)obj).name = label;
		Transform transform = model.transform;
		Transform transform2 = obj.transform;
		transform2.localPosition = prefabRoot.InverseTransformPoint(transform.position);
		transform2.localRotation = Quaternion.Inverse(prefabRoot.rotation) * transform.rotation;
		Vector3 lossyScale = transform.lossyScale;
		Vector3 lossyScale2 = prefabRoot.lossyScale;
		transform2.localScale = new Vector3(Ratio(lossyScale.x, lossyScale2.x), Ratio(lossyScale.y, lossyScale2.y), Ratio(lossyScale.z, lossyScale2.z));
		obj.SetActive(true);
		Strip(obj);
		return obj;
	}

	private static void Strip(GameObject copy)
	{
		ComponentBuffer.Clear();
		copy.GetComponentsInChildren<Component>(true, ComponentBuffer);
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < ComponentBuffer.Count; j++)
			{
				Component val = ComponentBuffer[j];
				if (!((Object)(object)val == (Object)null) && !Keep(val) && StripPass(val) == i)
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}
		ComponentBuffer.Clear();
	}

	private static bool Keep(Component component)
	{
		if (!(component is Transform) && !(component is Animator) && !(component is MeshFilter) && !(component is MeshRenderer))
		{
			return component is SkinnedMeshRenderer;
		}
		return true;
	}

	private static int StripPass(Component component)
	{
		if (component is Joint)
		{
			return 0;
		}
		if (component is Rigidbody)
		{
			return 2;
		}
		return 1;
	}

	private static float Ratio(float a, float b)
	{
		if (!(Mathf.Abs(b) > 1E-06f))
		{
			return a;
		}
		return a / b;
	}

	internal static bool HasFlapping(BirdKind kind, Animator animator)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Invalid comparison between Unknown and I4
		if (kind.FlapParam < 0)
		{
			if (!((Behaviour)animator).isActiveAndEnabled)
			{
				return false;
			}
			kind.FlapParam = 0;
			AnimatorControllerParameter[] parameters = animator.parameters;
			for (int i = 0; i < parameters.Length; i++)
			{
				if ((int)parameters[i].type == 4 && parameters[i].name == "flapping")
				{
					kind.FlapParam = 1;
					break;
				}
			}
			if (kind.FlapParam == 0)
			{
				Plugin.LogOnce("bird-flap-" + kind.Name, "The Dead Remain: the " + kind.Name + " animator has no 'flapping' switch; its birds only glide.");
			}
		}
		return kind.FlapParam == 1;
	}

	internal static BirdView Take(BirdKind kind)
	{
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Expected O, but got Unknown
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Expected O, but got Unknown
		while (kind.Free.Count > 0)
		{
			BirdView birdView = kind.Free.Pop();
			if (!((Object)(object)birdView.Root == (Object)null))
			{
				birdView.Root.SetActive(true);
				birdView.Reset();
				Live.Add(birdView);
				return birdView;
			}
		}
		if ((Object)(object)root == (Object)null)
		{
			root = new GameObject("TDR_Birds");
		}
		GameObject val = new GameObject("TDR_Bird_" + kind.Name);
		val.transform.SetParent(root.transform, false);
		BirdView birdView2 = new BirdView
		{
			Kind = kind,
			Root = val,
			T = val.transform
		};
		birdView2.Fly = Object.Instantiate<GameObject>(kind.FlyTemplate, val.transform, false);
		birdView2.Animator = birdView2.Fly.GetComponentInChildren<Animator>(true);
		if ((Object)(object)kind.LandTemplate != (Object)null)
		{
			birdView2.Land = Object.Instantiate<GameObject>(kind.LandTemplate, val.transform, false);
		}
		birdView2.Reset();
		Live.Add(birdView2);
		return birdView2;
	}

	internal static void Release(BirdView view)
	{
		if (view != null)
		{
			Live.Remove(view);
			if (!((Object)(object)view.Root == (Object)null))
			{
				view.Root.SetActive(false);
				view.Kind.Free.Push(view);
			}
		}
	}

	internal static void Caw(BirdKind kind, Vector3 position)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: 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)
		if (kind == null || kind.Caw == null || !kind.Caw.HasEffects())
		{
			return;
		}
		try
		{
			kind.Caw.Create(position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
		}
		catch (Exception ex)
		{
			Plugin.LogOnce("bird-caw", "The Dead Remain: a bird caw threw (" + ex.Message + ").");
		}
	}

	internal static void ClearAll()
	{
		for (int i = 0; i < Live.Count; i++)
		{
			if ((Object)(object)Live[i].Root != (Object)null)
			{
				Object.Destroy((Object)(object)Live[i].Root);
			}
		}
		Live.Clear();
		foreach (KeyValuePair<string, BirdKind> kind in Kinds)
		{
			if (kind.Value == null)
			{
				continue;
			}
			while (kind.Value.Free.Count > 0)
			{
				BirdView birdView = kind.Value.Free.Pop();
				if ((Object)(object)birdView.Root != (Object)null)
				{
					Object.Destroy((Object)(object)birdView.Root);
				}
			}
		}
		Kinds.Clear();
		if ((Object)(object)root != (Object)null)
		{
			Object.Destroy((Object)(object)root);
		}
		root = null;
		if ((Object)(object)holder != (Object)null)
		{
			Object.Destroy((Object)(object)holder);
		}
		holder = null;
	}
}
internal sealed class Flock
{
	private const float FlushCheckSeconds = 0.25f;

	private const float SpotSpacing = 0.7f;

	private const float AmbientCawMin = 25f;

	private const float AmbientCawMax = 60f;

	private const float TwoPi = (float)Math.PI * 2f;

	internal const float VanishMargin = 40f;

	internal readonly ZDOID Id;

	internal readonly BirdKind Kind;

	internal readonly List<Bird> Birds = new List<Bird>();

	internal readonly int Dir;

	internal readonly float ArrivalBearing;

	internal readonly string SpeciesName;

	internal Carcass Carcass;

	internal Vector3 Center;

	internal float Size;

	internal float Clock;

	internal bool Leaving;

	internal bool Visible;

	internal float AlarmLeft;

	internal float AlarmBlend;

	private readonly Random rng;

	private readonly float driftPhase;

	private bool intruderNear;

	private bool cawedThisFlush;

	private float nextFlushCheck;

	private float nextAmbientCaw;

	private static readonly RaycastHit[] Hits = (RaycastHit[])(object)new RaycastHit[16];

	private static int groundMask = -1;

	private static int skyMask;

	internal float BaseRadius => Mathf.Max(TdrConfig.CircleRadius.Value, Size + 4f);

	internal float BaseHeight => Mathf.Max(TdrConfig.CircleHeight.Value, Size + 4f);

	internal Vector3 CircleCentre => Center + new Vector3(Mathf.Sin(Clock * 0.031f + driftPhase) * 2.5f, 0f, Mathf.Cos(Clock * 0.027f + driftPhase * 1.3f) * 2.5f);

	internal float TouchdownDrop => Kind.FlyLift * TdrConfig.BirdScale.Value * 0.8f;

	internal float MinLandRadius => Mathf.Max(1f, Size * 0.45f + 0.4f);

	internal float MaxLandRadius => Mathf.Max(2.5f, MinLandRadius + 1.2f);

	internal bool Finished => Birds.Count == 0;

	internal int LandedCount
	{
		get
		{
			int num = 0;
			for (int i = 0; i < Birds.Count; i++)
			{
				if (Birds[i].State == BirdState.Feeding)
				{
					num++;
				}
			}
			return num;
		}
	}

	internal Flock(Carcass carcass, BirdKind kind, uint seed, int count, bool arrive)
	{
		//IL_0013: 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_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)
		Id = carcass.Id;
		Kind = kind;
		Carcass = carcass;
		Center = carcass.Center;
		Size = carcass.Size;
		SpeciesName = carcass.Species;
		rng = new Random((int)seed);
		Dir = (((seed & 1) == 0) ? 1 : (-1));
		ArrivalBearing = Range(0f, (float)Math.PI * 2f);
		driftPhase = Range(0f, (float)Math.PI * 2f);
		nextFlushCheck = Range(0f, 0.25f);
		nextAmbientCaw = Range(8f, 30f);
		float num = Range(0f, (float)Math.PI * 2f);
		float num2 = Range(2f, 5f);
		int num3 = 0;
		for (int i = 0; i < count; i++)
		{
			Bird bird = new Bird(this);
			Birds.Add(bird);
			float angle = num + (float)i * ((float)Math.PI * 2f) / (float)count + Range(-0.3f, 0.3f);
			if (arrive)
			{
				bird.State = BirdState.Waiting;
				bird.Delay = num2;
				num2 += Range(1.5f, 6f);
			}
			else if ((num3 + 1) * 2 <= count && Range(0f, 1f) < 0.5f && bird.PlaceLanded(this, angle))
			{
				num3++;
			}
			else
			{
				bird.PlaceOnCircle(this, angle);
			}
		}
	}

	internal float Range(float min, float max)
	{
		return min + (float)rng.NextDouble() * (max - min);
	}

	internal float LandingRadius()
	{
		return Range(MinLandRadius, MaxLandRadius);
	}

	internal bool WithinView(Vector3 cameraPos, float distance)
	{
		//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_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)
		Vector3 val = Center - cameraPos;
		return ((Vector3)(ref val)).sqrMagnitude < distance * distance;
	}

	internal bool AnyBirdWithin(Vector3 cameraPos, float distance)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_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)
		float num = distance * distance;
		for (int i = 0; i < Birds.Count; i++)
		{
			Bird bird = Birds[i];
			if (bird.State != BirdState.Waiting && bird.State != BirdState.Gone)
			{
				Vector3 val = bird.Pos - cameraPos;
				if (((Vector3)(ref val)).sqrMagnitude < num)
				{
					return true;
				}
			}
		}
		return false;
	}

	internal void Update(float dt, Vector3 cameraPos, float showDistance)
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		Clock += dt;
		if (!Leaving && (Object)(object)Carcass != (Object)null && Carcass.IsValid)
		{
			Center = Carcass.Center;
		}
		AlarmLeft = Mathf.Max(0f, AlarmLeft - dt);
		AlarmBlend = Mathf.MoveTowards(AlarmBlend, (AlarmLeft > 0f) ? 1f : 0f, dt / 5f);
		if (!Leaving)
		{
			nextFlushCheck -= dt;
			if (nextFlushCheck <= 0f)
			{
				nextFlushCheck = 0.25f;
				CheckFlush();
			}
			nextAmbientCaw -= dt;
			if (nextAmbientCaw <= 0f)
			{
				nextAmbientCaw = Range(25f, 60f);
				AmbientCaw();
			}
		}
		float num = showDistance + 40f;
		num *= num;
		bool flag = BirdKinds.IsReady(Kind);
		for (int num2 = Birds.Count - 1; num2 >= 0; num2--)
		{
			Bird bird = Birds[num2];
			bird.Update(this, dt);
			if (bird.State == BirdState.Leaving)
			{
				Vector3 val = bird.Pos - cameraPos;
				if (((Vector3)(ref val)).sqrMagnitude > num)
				{
					bird.Vanish();
				}
			}
			if (bird.State == BirdState.Gone)
			{
				BirdKinds.Release(bird.View);
				bird.View = null;
				Birds.RemoveAt(num2);
			}
			else
			{
				if (bird.State == BirdState.Waiting)
				{
					continue;
				}
				if (bird.View == null)
				{
					if (!flag)
					{
						continue;
					}
					bird.View = BirdKinds.Take(Kind);
				}
				bird.ApplyView(this);
			}
		}
	}

	internal void SetVisible(bool visible)
	{
		Visible = visible;
		if (!visible)
		{
			ReleaseAll();
		}
	}

	internal void ReleaseAll()
	{
		for (int i = 0; i < Birds.Count; i++)
		{
			if (Birds[i].View != null)
			{
				BirdKinds.Release(Birds[i].View);
				Birds[i].View = null;
			}
		}
	}

	private void CheckFlush()
	{
		//IL_0001: 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_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: 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)
		//IL_0087: 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_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_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: 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)
		Character val = NearestCharacter(Center, TdrConfig.FlushRange.Value);
		if ((Object)(object)val == (Object)null)
		{
			intruderNear = false;
			return;
		}
		if (!intruderNear)
		{
			intruderNear = true;
			cawedThisFlush = false;
		}
		Vector3 position = ((Component)val).transform.position;
		int num = 0;
		Vector3 position2 = Center;
		for (int i = 0; i < Birds.Count; i++)
		{
			Bird bird = Birds[i];
			if (bird.IsDown)
			{
				if (num == 0)
				{
					position2 = ((bird.State == BirdState.Feeding) ? (bird.Spot + Vector3.up * 0.3f) : bird.Pos);
				}
				bird.BeginScatter(this, position);
				num++;
			}
		}
		if (num != 0)
		{
			AlarmLeft = Mathf.Max(AlarmLeft, Range(20f, 40f));
			if (!cawedThisFlush)
			{
				cawedThisFlush = true;
				BirdKinds.Caw(Kind, position2);
			}
			if (Plugin.LogEvents)
			{
				Plugin.Event("birds flushed " + num + " at " + SpeciesName + " " + ((object)Id/*cast due to .constrained prefix*/).ToString() + " by " + Utils.GetPrefabName(((Component)val).gameObject));
			}
		}
	}

	private static Character NearestCharacter(Vector3 point, float range)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		List<Character> allCharacters = Character.GetAllCharacters();
		Character result = null;
		float num = range * range;
		for (int i = 0; i < allCharacters.Count; i++)
		{
			Character val = allCharacters[i];
			if (!((Object)(object)val == (Object)null) && !val.IsDead())
			{
				Vector3 val2 = ((Component)val).transform.position - point;
				float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
				if (!(sqrMagnitude >= num))
				{
					num = sqrMagnitude;
					result = val;
				}
			}
		}
		return result;
	}

	internal bool MayDescend()
	{
		if (Leaving || intruderNear || AlarmLeft > 0f)
		{
			return false;
		}
		if ((Object)(object)Carcass == (Object)null || !Carcass.IsFeedable)
		{
			return false;
		}
		int num = 0;
		int num2 = 0;
		for (int i = 0; i < Birds.Count; i++)
		{
			Bird bird = Birds[i];
			if (bird.State != BirdState.Waiting && bird.State != BirdState.Gone)
			{
				num++;
				if (bird.IsDown)
				{
					num2++;
				}
			}
		}
		return num2 * 2 < num;
	}

	private void AmbientCaw()
	{
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		if (Birds.Count == 0)
		{
			return;
		}
		int num = rng.Next(Birds.Count);
		for (int i = 0; i < Birds.Count; i++)
		{
			Bird bird = Birds[(num + i) % Birds.Count];
			if (bird.State == BirdState.Circling)
			{
				BirdKinds.Caw(Kind, bird.Pos);
				break;
			}
		}
	}

	internal void Leave()
	{
		//IL_0030: 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_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_004d: 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_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		if (Leaving)
		{
			return;
		}
		Leaving = true;
		intruderNear = false;
		float bearing = Range(0f, (float)Math.PI * 2f);
		if (BirdFlocks.HaveCamera)
		{
			Vector3 val = Center - BirdFlocks.CameraPos;
			if (val.x * val.x + val.z * val.z > 25f)
			{
				bearing = Mathf.Atan2(val.z, val.x) + Range(-0.5f, 0.5f);
			}
		}
		for (int i = 0; i < Birds.Count; i++)
		{
			Birds[i].BeginLeaving(this, bearing);
		}
	}

	internal void Rejoin(Carcass carcass)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		Leaving = false;
		Carcass = carcass;
		Center = carcass.Center;
		Size = carcass.Size;
		for (int i = 0; i < Birds.Count; i++)
		{
			Birds[i].Rejoin(this);
		}
	}

	internal bool FindSpot(Bird self, Vector3 near, out Vector3 spot)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing refere