Decompiled source of SkeletonCrew v1.0.2

SkeletonCrew.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SkeletonCrew.Ai;
using SkeletonCrew.Diagnostics;
using SkeletonCrew.Jobs;
using SkeletonCrew.Patches;
using SkeletonCrew.Ui;
using Splatform;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("Vash")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Makes vanilla Blood Magic summons regenerate, survive portals, fight smarter and take orders.")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2+119317f8ff839fddaaedb7f65472ad5cea0434bb")]
[assembly: AssemblyProduct("SkeletonCrew")]
[assembly: AssemblyTitle("SkeletonCrew")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SkeletonCrew
{
	internal static class Commands
	{
		internal struct LookResult
		{
			internal Character Target;

			internal Character Friendly;

			internal Vector3 Point;

			internal bool HasPoint;

			internal HarvestTarget Harvest;

			internal string HarvestRefusal;

			internal string HitName;
		}

		internal enum OrderAction
		{
			None,
			MoveHere,
			Attack,
			Harvest,
			HarvestArea,
			Guard,
			Recall
		}

		private static int _tapCount;

		private static float _lastTapTime;

		private static LookResult _tapLook;

		private const float SnapSearchRadius = 6f;

		private static string _pendingMessage;

		internal static void HandleInput()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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)
			if (IsTextInputActive() || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			KeyboardShortcut value = SkeletonCrewPlugin.MenuKey.Value;
			if (Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				CrewMenu.Toggle();
			}
			else if (!CrewMenu.HandleInput())
			{
				value = SkeletonCrewPlugin.CycleSummonTypeKey.Value;
				if (Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
				{
					CycleSummonType();
				}
				value = SkeletonCrewPlugin.StanceKey.Value;
				if (Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
				{
					Stance.Cycle();
				}
				value = SkeletonCrewPlugin.SelectionKey.Value;
				if (Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
				{
					CrewSelection.Cycle();
				}
				HandleMultiTap();
				FlushPendingMessage();
			}
		}

		private static void HandleMultiTap()
		{
			//IL_0005: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = SkeletonCrewPlugin.CommandButton.Value;
			if (Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey))
			{
				float value2 = SkeletonCrewPlugin.MultiTapSeconds.Value;
				if (_tapCount == 0 || Time.time - _lastTapTime > value2)
				{
					_tapCount = 1;
					_tapLook = Look();
				}
				else
				{
					_tapCount++;
				}
				_lastTapTime = Time.time;
				switch (_tapCount)
				{
				case 1:
					Execute((!((Object)(object)_tapLook.Target != (Object)null)) ? OrderAction.MoveHere : OrderAction.Attack, _tapLook);
					break;
				case 2:
					Follow();
					break;
				default:
					HoldAndGuard();
					break;
				}
			}
		}

		internal static void Execute(OrderAction action, LookResult look)
		{
			switch (action)
			{
			case OrderAction.Attack:
				Attack(look);
				break;
			case OrderAction.MoveHere:
				MoveOrGuard(look, guard: false);
				break;
			case OrderAction.Guard:
				MoveOrGuard(look, guard: true);
				break;
			case OrderAction.Harvest:
				Harvest(look, area: false);
				break;
			case OrderAction.HarvestArea:
				Harvest(look, area: true);
				break;
			case OrderAction.Recall:
				RecallAll();
				break;
			}
		}

		private static void Follow()
		{
			//IL_002c: 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_0042: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			int num = SummonRegistry.AdoptOrphans(localPlayer, SkeletonCrewPlugin.CommandRadius.Value);
			foreach (SummonRegistry.Summon item in InRange())
			{
				SummonRegistry.ClearStation(item.Id);
				SummonRegistry.ClearMove(item.Id);
				SummonRegistry.ClearJob(item.Id);
				SummonRegistry.Obey(item.Id, item.AI);
				SummonRegistry.GrantRecallGrace(item.Id);
				SummonRegistry.SetRegrouping(item.Id, value: true);
				if (SetFollowState(item, follow: true, localPlayer))
				{
					num++;
				}
			}
			Report("follow me", num);
		}

		private static void HoldAndGuard()
		{
			//IL_0025: 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_0044: 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_006d: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			int num = 0;
			List<ZDOID> list = new List<ZDOID>();
			foreach (SummonRegistry.Summon item in InRange())
			{
				SummonRegistry.ClearMove(item.Id);
				SummonRegistry.Obey(item.Id, item.AI);
				SummonRegistry.SetRegrouping(item.Id, value: false);
				if (SetFollowState(item, follow: false, localPlayer))
				{
					SummonRegistry.SetStation(item.Id, ((Component)item.Character).transform.position);
					list.Add(item.Id);
					num++;
				}
			}
			AssignGuardSlots(list, ((Object)(object)localPlayer != (Object)null) ? ((Component)localPlayer).transform.position : Vector3.zero);
			Report("hold position", num);
		}

		private static void Attack(LookResult look)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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)
			if ((Object)(object)look.Target == (Object)null)
			{
				SkeletonCrewPlugin.Log.LogInfo((object)"Order 'attack': nothing targetable under the crosshair.");
				return;
			}
			int num = 0;
			foreach (SummonRegistry.Summon item in InRange())
			{
				if (!((Object)(object)item.AI == (Object)null))
				{
					SummonRegistry.ClearStation(item.Id);
					SummonRegistry.ClearMove(item.Id);
					SummonRegistry.SetRegrouping(item.Id, value: false);
					((BaseAI)item.AI).ResetPatrolPoint();
					SummonRegistry.OrderAttack(item.Id, look.Target);
					SummonRegistry.Retarget(item.AI, look.Target);
					((BaseAI)item.AI).SetAlerted(true);
					num++;
				}
			}
			Report("attack " + look.Target.GetHoverName(), num);
		}

		private static void MoveOrGuard(LookResult look, bool guard)
		{
			//IL_0019: 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_0067: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: 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_0124: Unknown result type (might be due to invalid IL or missing references)
			if (!look.HasPoint)
			{
				SkeletonCrewPlugin.Log.LogInfo((object)"Order 'move': no ground point under the crosshair.");
			}
			else
			{
				if (RefusedAsLava(look.Point, "move"))
				{
					return;
				}
				_ = Player.m_localPlayer;
				int num = 0;
				List<ZDOID> list = new List<ZDOID>();
				List<SummonRegistry.Summon> list2 = new List<SummonRegistry.Summon>(InRange());
				Vector3 point = look.Point;
				if (RefusedAsUnreachable(list2, ref point, guard ? "guard" : "move"))
				{
					return;
				}
				look.Point = point;
				bool spread = list2.Count > 1;
				foreach (SummonRegistry.Summon item in list2)
				{
					if (!((Object)(object)item.AI == (Object)null))
					{
						SummonRegistry.Obey(item.Id, item.AI);
						SummonRegistry.SetRegrouping(item.Id, value: false);
						SummonRegistry.ClearJob(item.Id);
						item.AI.SetFollowTarget((GameObject)null);
						SummonRegistry.OrderMove(item.Id, look.Point, spread);
						((BaseAI)item.AI).ResetPatrolPoint();
						((BaseAI)item.AI).SetPatrolPoint(look.Point);
						if (guard)
						{
							SummonRegistry.SetStation(item.Id, look.Point);
							list.Add(item.Id);
						}
						else
						{
							SummonRegistry.ClearStation(item.Id);
						}
						num++;
					}
				}
				AssignGuardSlots(list, look.Point);
				Report(guard ? "guard here" : "move here", num);
			}
		}

		private static void AssignGuardSlots(List<ZDOID> guards, Vector3 anchor)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < guards.Count; i++)
			{
				SummonRegistry.SetGuardSlot(guards[i], i, guards.Count, anchor);
			}
		}

		internal static void FollowFromMenu()
		{
			Follow();
		}

		internal static void HoldFromMenu()
		{
			HoldAndGuard();
		}

		internal static void DismissAllFromMenu()
		{
			int num = 0;
			foreach (SummonRegistry.Summon item in SummonRegistry.Owned)
			{
				if (!((Object)(object)item.Character == (Object)null) && !item.Character.IsDead() && !((Object)(object)item.Tameable == (Object)null) && TameableCullWeakestPatch.Dismiss(item.Tameable))
				{
					num++;
				}
			}
			num += DismissAway();
			SkeletonCrewPlugin.Log.LogInfo((object)$"Dismissed {num} summon(s) from the menu.");
		}

		private static int DismissAway()
		{
			//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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (ZDOMan.instance == null)
			{
				return 0;
			}
			List<ZDOID> list = new List<ZDOID>();
			CrewHud.CollectAway(list);
			int num = 0;
			foreach (ZDOID item in list)
			{
				ZDO zDO = ZDOMan.instance.GetZDO(item);
				CrewHud.Forget(item);
				if (zDO != null && SummonRegistry.IsOurs(zDO))
				{
					zDO.SetOwner(ZDOMan.GetSessionID());
					ZDOMan.instance.DestroyZDO(zDO);
					num++;
				}
			}
			if (num > 0)
			{
				SkeletonCrewPlugin.Log.LogInfo((object)$"Dismissed {num} summon(s) that were out of range.");
			}
			return num;
		}

		private static void CycleSummonType()
		{
			SummonPreference[] array = (SummonPreference[])Enum.GetValues(typeof(SummonPreference));
			int num = Array.IndexOf(array, SkeletonCrewPlugin.SummonWeaponPreference.Value);
			SummonPreference summonPreference = SkeletonCrewPlugin.SummonWeaponPreference.Value;
			for (int i = 1; i <= array.Length; i++)
			{
				SummonPreference summonPreference2 = array[(num + i + array.Length) % array.Length];
				if ((summonPreference2 != SummonPreference.Adaptive || SkeletonCrewPlugin.EnableAdaptive.Value) && Progression.IsUnlocked(summonPreference2))
				{
					summonPreference = summonPreference2;
					break;
				}
			}
			bool isArmed = SummonGroup.IsArmed;
			SummonGroup.Disarm();
			SkeletonCrewPlugin.SummonWeaponPreference.Value = summonPreference;
			SkeletonCrewPlugin.Log.LogInfo((object)$"Next summon: {summonPreference}.");
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, isArmed ? $"Next raise: {summonPreference} - group off" : $"Next raise: {summonPreference}", 0, (Sprite)null, false);
			}
		}

		private static bool RefusedAsLava(Vector3 point, string order)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (!LavaGuard.IsLava(point))
			{
				return false;
			}
			SkeletonCrewPlugin.Log.LogInfo((object)("Order '" + order + "': refused. Destination is lava."));
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, "Won't go there - that's lava", 0, (Sprite)null, false);
			}
			return true;
		}

		private static bool AnyPathTo(List<SummonRegistry.Summon> recipients, Vector3 target, AgentType agent)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			foreach (SummonRegistry.Summon recipient in recipients)
			{
				if ((Object)(object)recipient.Character != (Object)null && Pathfinding.instance.HavePath(((Component)recipient.Character).transform.position, target, agent))
				{
					return true;
				}
			}
			return false;
		}

		private static bool RefusedAsUnreachable(List<SummonRegistry.Summon> recipients, ref Vector3 point, string order)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0067: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_008b: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Pathfinding.instance == (Object)null || recipients.Count == 0)
			{
				return false;
			}
			Vector3 val = point;
			AgentType val2 = (AgentType)(((Object)(object)recipients[0].AI == (Object)null) ? 13 : ((int)((BaseAI)recipients[0].AI).m_pathAgentType));
			AgentSettings settings = Pathfinding.instance.GetSettings(val2);
			if (settings != null)
			{
				Pathfinding.instance.SnapToNavMesh(ref val, true, settings);
			}
			Vector3 val3 = default(Vector3);
			if (!AnyPathTo(recipients, val, val2) && Pathfinding.instance.FindValidPoint(ref val3, point, 6f, val2) && AnyPathTo(recipients, val3, val2))
			{
				SkeletonCrewPlugin.Log.LogInfo((object)("Order '" + order + "': the exact spot is off the navmesh; using walkable ground " + $"{Vector3.Distance(point, val3):0.#}m away."));
				val = val3;
			}
			point = val;
			int num = 0;
			for (int num2 = recipients.Count - 1; num2 >= 0; num2--)
			{
				SummonRegistry.Summon summon = recipients[num2];
				if (!((Object)(object)summon.Character == (Object)null) && !((Object)(object)summon.AI == (Object)null) && !Pathfinding.instance.HavePath(((Component)summon.Character).transform.position, val, ((BaseAI)summon.AI).m_pathAgentType))
				{
					recipients.RemoveAt(num2);
					num++;
				}
			}
			if (num == 0)
			{
				return false;
			}
			if (recipients.Count > 0)
			{
				SkeletonCrewPlugin.Log.LogInfo((object)$"Order '{order}': {num} summon(s) have no path there and were left out.");
				return false;
			}
			SkeletonCrewPlugin.Log.LogInfo((object)$"Order '{order}': refused. No summon has a path to {point}.");
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, "They can't get there from here", 0, (Sprite)null, false);
			}
			return true;
		}

		private static void Harvest(LookResult look, bool area)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			if (look.Harvest == null || look.Harvest.Kind == HarvestKind.None)
			{
				SkeletonCrewPlugin.Log.LogInfo((object)"Order 'harvest': nothing harvestable under the crosshair.");
			}
			else
			{
				if (look.HasPoint && RefusedAsLava(look.Point, "harvest"))
				{
					return;
				}
				int num = ToolTier.BestFor(look.Harvest.Kind);
				if (num < look.Harvest.MinToolTier)
				{
					string text = $"Need tool tier {look.Harvest.MinToolTier} - your best is {num}";
					SkeletonCrewPlugin.Log.LogInfo((object)("Order 'harvest " + look.Harvest.Name + "': refused. " + text + "."));
					if ((Object)(object)MessageHud.instance != (Object)null)
					{
						MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false);
					}
					return;
				}
				Vector3 position = look.Harvest.Position;
				List<HarvestTarget> list = (area ? HarvestScan.Gather(position, SkeletonCrewPlugin.HarvestAreaRadius.Value, look.Harvest.Kind) : null);
				if (list != null && look.Harvest.Kind == HarvestKind.Pick)
				{
					string wanted = look.Harvest.PrefabName;
					list.RemoveAll((HarvestTarget t) => t.PrefabName != wanted);
				}
				Dictionary<GameObject, int> assigned = new Dictionary<GameObject, int>();
				int num2 = 0;
				List<SummonRegistry.Summon> list2 = new List<SummonRegistry.Summon>(InRange());
				Vector3 point = look.Harvest.WorkPosition((list2.Count > 0 && (Object)(object)list2[0].Character != (Object)null) ? ((Component)list2[0].Character).transform.position : ((Component)Player.m_localPlayer).transform.position);
				if (RefusedAsUnreachable(list2, ref point, "harvest"))
				{
					return;
				}
				foreach (SummonRegistry.Summon item in list2)
				{
					SummonRegistry.ClearStation(item.Id);
					SummonRegistry.ClearMove(item.Id);
					SummonRegistry.SetRegrouping(item.Id, value: false);
					HarvestTarget target = NextForSpread(list, item, assigned, look.Harvest) ?? look.Harvest.Copy();
					SummonRegistry.OrderHarvest(item.Id, target, area, position);
					num2++;
				}
				Report(area ? ("harvest area around " + look.Harvest.Name) : ("harvest " + look.Harvest.Name), num2);
			}
		}

		private static HarvestTarget NextForSpread(List<HarvestTarget> spread, SummonRegistry.Summon s, Dictionary<GameObject, int> assigned, HarvestTarget primary)
		{
			//IL_0062: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if (spread == null || (Object)(object)s.Character == (Object)null)
			{
				return null;
			}
			if ((Object)(object)primary?.Root != (Object)null)
			{
				assigned.TryGetValue(primary.Root, out var value);
				if (value < primary.WorkerCapacity)
				{
					assigned[primary.Root] = value + 1;
					return primary.Copy();
				}
			}
			Vector3 position = ((Component)s.Character).transform.position;
			HarvestTarget harvestTarget = null;
			float num = float.MaxValue;
			foreach (HarvestTarget item in spread)
			{
				assigned.TryGetValue(item.Root, out var value2);
				if (value2 < item.WorkerCapacity)
				{
					Vector3 val = item.Position - position;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						harvestTarget = item;
					}
				}
			}
			if (harvestTarget == null)
			{
				return null;
			}
			assigned.TryGetValue(harvestTarget.Root, out var value3);
			assigned[harvestTarget.Root] = value3 + 1;
			return harvestTarget.Copy();
		}

		private static void RecallAll()
		{
			//IL_0039: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			int num = 0;
			foreach (SummonRegistry.Summon item in SummonRegistry.Owned)
			{
				if (!((Object)(object)item.Character == (Object)null) && !item.Character.IsDead())
				{
					SummonRegistry.ClearStation(item.Id);
					Recall.Bring(item, localPlayer, "ordered", Vector3.Distance(((Component)item.Character).transform.position, ((Component)localPlayer).transform.position));
					num++;
				}
			}
			Report("recall to me", num);
		}

		private static bool SetFollowState(SummonRegistry.Summon s, bool follow, Player player)
		{
			if ((Object)(object)s.AI == (Object)null)
			{
				return false;
			}
			if ((Object)(object)s.AI.GetFollowTarget() != (Object)null == follow)
			{
				return true;
			}
			if (follow)
			{
				((BaseAI)s.AI).ResetPatrolPoint();
				s.AI.SetFollowTarget(((Component)player).gameObject);
				SummonRegistry.MarkOwned(s.Character, player);
				return true;
			}
			s.AI.SetFollowTarget((GameObject)null);
			((BaseAI)s.AI).SetPatrolPoint();
			return true;
		}

		internal static LookResult Look()
		{
			//IL_005b: 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_003d: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			LookResult result = default(LookResult);
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return result;
			}
			float value = SkeletonCrewPlugin.TargetRange.Value;
			float value2 = SkeletonCrewPlugin.TargetAssistRadius.Value;
			RaycastHit[] obj = ((value2 > 0f) ? Physics.SphereCastAll(((Component)main).transform.position, value2, ((Component)main).transform.forward, value) : Physics.RaycastAll(((Component)main).transform.position, ((Component)main).transform.forward, value));
			Array.Sort(obj, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
			RaycastHit[] array = obj;
			for (int num = 0; num < array.Length; num++)
			{
				RaycastHit val = array[num];
				bool flag = ((RaycastHit)(ref val)).distance <= 0f;
				Character componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Character>();
				if ((Object)(object)componentInParent == (Object)null)
				{
					if (result.Harvest == null)
					{
						result.Harvest = HarvestTarget.Resolve(((RaycastHit)(ref val)).collider);
						if (result.Harvest == null && result.HarvestRefusal == null)
						{
							result.HarvestRefusal = HarvestTarget.LastRefusal;
						}
					}
					if (!result.HasPoint && !flag)
					{
						result.Point = ((RaycastHit)(ref val)).point;
						result.HasPoint = true;
						result.HitName = (((Object)(object)((RaycastHit)(ref val)).collider == (Object)null) ? null : ((Object)((Component)((RaycastHit)(ref val)).collider).transform.root).name);
					}
				}
				else
				{
					if (componentInParent.IsDead() || (Object)(object)componentInParent == (Object)(object)Player.m_localPlayer)
					{
						continue;
					}
					if (componentInParent.IsPlayer() || componentInParent.IsTamed())
					{
						if ((Object)(object)result.Friendly == (Object)null)
						{
							result.Friendly = componentInParent;
						}
					}
					else if ((Object)(object)result.Target == (Object)null)
					{
						result.Target = componentInParent;
					}
				}
			}
			return result;
		}

		private static bool IsTextInputActive()
		{
			if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible() && !StoreGui.IsVisible())
			{
				if ((Object)(object)TextInput.instance != (Object)null && (Object)(object)TextInput.instance.m_panel != (Object)null)
				{
					return TextInput.instance.m_panel.activeSelf;
				}
				return false;
			}
			return true;
		}

		private static IEnumerable<SummonRegistry.Summon> InRange()
		{
			Player player = Player.m_localPlayer;
			float value = SkeletonCrewPlugin.CommandRadius.Value;
			bool limited = value > 0f;
			float radiusSq = value * value;
			foreach (SummonRegistry.Summon item in SummonRegistry.Owned)
			{
				if ((Object)(object)item.Character == (Object)null || item.Character.IsDead() || !CrewSelection.Applies(item.Id))
				{
					continue;
				}
				if (limited)
				{
					Vector3 val = ((Component)item.Character).transform.position - ((Component)player).transform.position;
					if (((Vector3)(ref val)).sqrMagnitude > radiusSq)
					{
						continue;
					}
				}
				yield return item;
			}
		}

		private static void Report(string order, int count)
		{
			SkeletonCrewPlugin.Log.LogInfo((object)$"Order '{order}': {count} summon(s).");
			if (count > 0 && SkeletonCrewPlugin.ShowOrderMessages.Value)
			{
				_pendingMessage = $"Crew: {order} ({count})";
			}
		}

		private static void FlushPendingMessage()
		{
			if (_pendingMessage != null && _tapCount != 0 && !(Time.time - _lastTapTime <= SkeletonCrewPlugin.MultiTapSeconds.Value))
			{
				if ((Object)(object)MessageHud.instance != (Object)null)
				{
					MessageHud.instance.ShowMessage((MessageType)1, _pendingMessage, 0, (Sprite)null, false);
				}
				_pendingMessage = null;
				_tapCount = 0;
			}
		}
	}
	internal static class CrewHud
	{
		private sealed class Row
		{
			internal GameObject Root;

			internal Image Portrait;

			internal Text Label;

			internal Image BarFill;
		}

		private struct Entry
		{
			internal ZDOID Id;

			internal string Name;

			internal float Fraction;

			internal string Activity;

			internal ItemData Weapon;

			internal string Tag;

			internal bool Away;
		}

		private sealed class NameOrder : IComparer<Entry>
		{
			public int Compare(Entry a, Entry b)
			{
				return string.CompareOrdinal(a.Name, b.Name);
			}
		}

		private static GameObject _panel;

		private static RectTransform _rect;

		private static Text _header;

		private static Transform _attachedTo;

		private static int _headerCrew = -1;

		private static CrewStance _headerStance;

		private static ZDOID _headerSelected;

		private static bool _headerAll;

		private static readonly List<Row> Rows = new List<Row>();

		private const int RowHeight = 34;

		private const int PanelWidth = 210;

		private static readonly Dictionary<ZDOID, string> Seen = new Dictionary<ZDOID, string>();

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

		private static readonly List<Entry> Entries = new List<Entry>();

		private static readonly List<Entry> Away = new List<Entry>();

		private static float _nextAwayScan;

		private const float AwayScanInterval = 0.5f;

		private static readonly NameOrder ByName = new NameOrder();

		private static readonly string[] ActivityNames = BuildActivityNames();

		internal static void Reset()
		{
			if ((Object)(object)_panel != (Object)null)
			{
				Object.Destroy((Object)(object)_panel);
			}
			_panel = null;
			_header = null;
			_attachedTo = null;
			Rows.Clear();
			Seen.Clear();
		}

		internal static void Tick()
		{
			if (!SkeletonCrewPlugin.ShowCrewHud.Value || (SummonRegistry.Owned.Count == 0 && Seen.Count == 0))
			{
				if ((Object)(object)_panel != (Object)null)
				{
					_panel.SetActive(false);
				}
				return;
			}
			Transform val = CurrentParent();
			if (!((Object)(object)val == (Object)null))
			{
				if ((Object)(object)_panel == (Object)null)
				{
					Build(val);
				}
				if ((Object)(object)_attachedTo != (Object)(object)val)
				{
					_panel.transform.SetParent(val, false);
					_attachedTo = val;
				}
				_panel.SetActive(true);
				Refresh();
			}
		}

		private static Transform CurrentParent()
		{
			return UiRoot.Current();
		}

		private static void Build(Transform parent)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_00ac: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			Rows.Clear();
			_panel = new GameObject("SkeletonCrewHud", new Type[2]
			{
				typeof(RectTransform),
				typeof(CanvasGroup)
			});
			_panel.transform.SetParent(parent, false);
			_attachedTo = parent;
			_rect = _panel.GetComponent<RectTransform>();
			Anchor(_rect);
			CanvasGroup component = _panel.GetComponent<CanvasGroup>();
			component.interactable = false;
			component.blocksRaycasts = false;
			_header = MakeText(_panel.transform, 13, (FontStyle)1);
			RectTransform component2 = ((Component)_header).GetComponent<RectTransform>();
			component2.anchorMin = new Vector2(0f, 1f);
			component2.anchorMax = new Vector2(1f, 1f);
			component2.pivot = new Vector2(0f, 1f);
			component2.anchoredPosition = Vector2.zero;
			component2.sizeDelta = new Vector2(0f, 20f);
		}

		private static void Anchor(RectTransform rect)
		{
			//IL_000b: 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_0035: 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_006a: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = new Vector2(0f, 1f);
			rect.anchorMax = new Vector2(0f, 1f);
			rect.pivot = new Vector2(0f, 1f);
			rect.anchoredPosition = new Vector2(SkeletonCrewPlugin.CrewHudX.Value, 0f - SkeletonCrewPlugin.CrewHudY.Value);
			rect.sizeDelta = new Vector2(210f, 200f);
			((Transform)rect).localScale = Vector3.one * SkeletonCrewPlugin.CrewHudScale.Value;
		}

		internal static void CollectAway(List<ZDOID> into)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyValuePair<ZDOID, string> item in Seen)
			{
				bool flag = false;
				foreach (SummonRegistry.Summon item2 in SummonRegistry.Owned)
				{
					if (item2.Id == item.Key)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					into.Add(item.Key);
				}
			}
		}

		internal static void Forget(ZDOID id)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Seen.Remove(id);
		}

		private static void Refresh()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			Anchor(_rect);
			List<Entry> list = BuildEntries();
			if (list.Count != _headerCrew || Stance.Current != _headerStance || CrewSelection.Selected != _headerSelected || CrewSelection.IsAll != _headerAll)
			{
				_headerCrew = list.Count;
				_headerStance = Stance.Current;
				_headerSelected = CrewSelection.Selected;
				_headerAll = CrewSelection.IsAll;
				_header.text = $"CREW [{list.Count}] — {Stance.Current.ToString().ToUpperInvariant()}" + "   <color=#FFD479>▸ " + CrewSelection.Describe().ToUpperInvariant() + "</color>";
			}
			while (Rows.Count < list.Count)
			{
				Rows.Add(MakeRow(Rows.Count));
			}
			for (int i = 0; i < Rows.Count; i++)
			{
				if (i >= list.Count)
				{
					Rows[i].Root.SetActive(false);
					continue;
				}
				Rows[i].Root.SetActive(true);
				Fill(Rows[i], list[i]);
			}
		}

		private static List<Entry> BuildEntries()
		{
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: 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_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			bool flag = Time.time >= _nextAwayScan;
			if (flag)
			{
				_nextAwayScan = Time.time + 0.5f;
			}
			Away.Clear();
			foreach (Entry entry in Entries)
			{
				if (entry.Away)
				{
					Away.Add(entry);
				}
			}
			Entries.Clear();
			foreach (SummonRegistry.Summon item in SummonRegistry.Owned)
			{
				Character character = item.Character;
				if (!((Object)(object)character == (Object)null))
				{
					string hoverName = character.GetHoverName();
					Seen[item.Id] = hoverName;
					Humanoid val = (Humanoid)(object)((character is Humanoid) ? character : null);
					Entries.Add(new Entry
					{
						Id = item.Id,
						Name = hoverName,
						Fraction = Mathf.Clamp01(character.GetHealth() / Mathf.Max(1f, character.GetMaxHealth())),
						Activity = Activity(item),
						Weapon = ((val != null) ? val.GetCurrentWeapon() : null),
						Tag = RoleTag(val),
						Away = false
					});
				}
			}
			if (!flag)
			{
				foreach (Entry item2 in Away)
				{
					if (!IsListed(item2.Id))
					{
						Entries.Add(item2);
					}
				}
				return Entries;
			}
			ZDOMan instance = ZDOMan.instance;
			if (instance == null)
			{
				foreach (Entry item3 in Away)
				{
					if (!IsListed(item3.Id))
					{
						Entries.Add(item3);
					}
				}
				return Entries;
			}
			Forgotten.Clear();
			int count = Entries.Count;
			foreach (KeyValuePair<ZDOID, string> item4 in Seen)
			{
				if (!IsListed(item4.Key))
				{
					ZDO zDO = instance.GetZDO(item4.Key);
					if (zDO == null)
					{
						Forgotten.Add(item4.Key);
						continue;
					}
					float num = Mathf.Max(1f, zDO.GetFloat(ZDOVars.s_maxHealth, 1f));
					Entries.Add(new Entry
					{
						Id = item4.Key,
						Name = item4.Value,
						Fraction = Mathf.Clamp01(zDO.GetFloat(ZDOVars.s_health, num) / num),
						Activity = "away",
						Weapon = null,
						Away = true
					});
				}
			}
			foreach (ZDOID item5 in Forgotten)
			{
				Seen.Remove(item5);
			}
			Entries.Sort(count, Entries.Count - count, ByName);
			return Entries;
		}

		private static bool IsListed(ZDOID id)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			foreach (Entry entry in Entries)
			{
				if (entry.Id == id)
				{
					return true;
				}
			}
			return false;
		}

		private static void Fill(Row row, Entry e)
		{
			//IL_0016: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			((Graphic)row.BarFill).rectTransform.anchorMax = new Vector2(e.Fraction, 1f);
			((Graphic)row.BarFill).color = HealthColour(e.Fraction);
			Sprite val = WeaponIcon(e.Weapon);
			row.Portrait.sprite = val;
			((Behaviour)row.Portrait).enabled = (Object)(object)val != (Object)null;
			bool flag = !e.Away && CrewSelection.Applies(e.Id);
			bool flag2 = flag && !CrewSelection.IsAll;
			((Graphic)row.Label).color = (Color)(flag ? Color.white : new Color(0.45f, 0.45f, 0.45f));
			((Graphic)row.Portrait).color = (Color)(flag ? Color.white : new Color(1f, 1f, 1f, 0.35f));
			row.Label.text = (flag2 ? "<color=#FFD479>▸</color>" : " ") + (e.Away ? string.Empty : ("<color=#9FD0FF>" + e.Tag + "</color> ")) + e.Name + "   <color=#BBBBBB>" + e.Activity + "</color>";
		}

		private static Sprite WeaponIcon(ItemData weapon)
		{
			Sprite[] array = weapon?.m_shared?.m_icons;
			if (array == null || array.Length == 0)
			{
				return null;
			}
			return array[Mathf.Clamp(weapon.m_variant, 0, array.Length - 1)];
		}

		private static string RoleTag(Humanoid h)
		{
			SummonPreference? summonPreference = SummonClass.Of(h);
			string text = ((!summonPreference.HasValue) ? null : TagFor(summonPreference.Value));
			if (text != null)
			{
				return text;
			}
			if (!WeaponChoice.IsRanged((h == null) ? null : h.GetCurrentWeapon()?.m_shared))
			{
				return "[M]";
			}
			return "[R]";
		}

		private static string TagFor(SummonPreference pref)
		{
			return pref switch
			{
				SummonPreference.Defender => "[D]", 
				SummonPreference.Healer => "[H]", 
				SummonPreference.FireMage => "[F]", 
				SummonPreference.IceMage => "[I]", 
				_ => null, 
			};
		}

		private static string[] BuildActivityNames()
		{
			Activity[] array = (Activity[])Enum.GetValues(typeof(Activity));
			string[] array2 = new string[array.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array2[(int)array[i]] = array[i].ToString();
			}
			return array2;
		}

		private static string Activity(SummonRegistry.Summon s)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			int activity = (int)SummonRegistry.IntentFor(s.Id).Activity;
			if (activity < 0 || activity >= ActivityNames.Length)
			{
				return "?";
			}
			return ActivityNames[activity];
		}

		private static Color HealthColour(float fraction)
		{
			//IL_0049: 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_001f: Unknown result type (might be due to invalid IL or missing references)
			if (!(fraction > 0.6f))
			{
				if (!(fraction > 0.3f))
				{
					return new Color(0.85f, 0.3f, 0.25f);
				}
				return new Color(0.9f, 0.75f, 0.25f);
			}
			return new Color(0.45f, 0.8f, 0.4f);
		}

		private static Row MakeRow(int index)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: 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_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Expected O, but got Unknown
			//IL_023e: 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_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Expected O, but got Unknown
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject($"Row{index}", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent(_panel.transform, false);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0f, 1f);
			component.anchorMax = new Vector2(1f, 1f);
			component.pivot = new Vector2(0f, 1f);
			component.anchoredPosition = new Vector2(0f, -22f - (float)(index * 34));
			component.sizeDelta = new Vector2(0f, 34f);
			GameObject val2 = new GameObject("Portrait", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val2.transform.SetParent(val.transform, false);
			((Behaviour)val2.GetComponent<Image>()).enabled = false;
			RectTransform component2 = val2.GetComponent<RectTransform>();
			component2.anchorMin = new Vector2(0f, 0.5f);
			component2.anchorMax = new Vector2(0f, 0.5f);
			component2.pivot = new Vector2(0f, 0.5f);
			component2.anchoredPosition = new Vector2(0f, 0f);
			component2.sizeDelta = new Vector2(28f, 28f);
			Text val3 = MakeText(val.transform, 12, (FontStyle)0);
			RectTransform component3 = ((Component)val3).GetComponent<RectTransform>();
			component3.anchorMin = new Vector2(0f, 1f);
			component3.anchorMax = new Vector2(1f, 1f);
			component3.pivot = new Vector2(0f, 1f);
			component3.anchoredPosition = new Vector2(32f, -1f);
			component3.sizeDelta = new Vector2(-32f, 16f);
			GameObject val4 = new GameObject("BarBack", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val4.transform.SetParent(val.transform, false);
			((Graphic)val4.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.55f);
			RectTransform component4 = val4.GetComponent<RectTransform>();
			component4.anchorMin = new Vector2(0f, 1f);
			component4.anchorMax = new Vector2(1f, 1f);
			component4.pivot = new Vector2(0f, 1f);
			component4.anchoredPosition = new Vector2(32f, -18f);
			component4.sizeDelta = new Vector2(-36f, 8f);
			GameObject val5 = new GameObject("BarFill", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val5.transform.SetParent(val4.transform, false);
			((Graphic)val5.GetComponent<Image>()).color = HealthColour(1f);
			RectTransform component5 = val5.GetComponent<RectTransform>();
			component5.anchorMin = Vector2.zero;
			component5.anchorMax = Vector2.one;
			component5.offsetMin = Vector2.zero;
			component5.offsetMax = Vector2.zero;
			return new Row
			{
				Root = val,
				Portrait = val2.GetComponent<Image>(),
				Label = val3,
				BarFill = val5.GetComponent<Image>()
			};
		}

		private static Text MakeText(Transform parent, int size, FontStyle style)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return UiRoot.MakeText(parent, size, style);
		}
	}
	internal static class MapPins
	{
		private static readonly Dictionary<ZDOID, PinData> Pins = new Dictionary<ZDOID, PinData>();

		internal static void Tick()
		{
			//IL_0058: 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_00a7: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			if (!SkeletonCrewPlugin.ShowOnMap.Value)
			{
				if (Pins.Count > 0)
				{
					Clear();
				}
			}
			else
			{
				if ((Object)(object)Minimap.instance == (Object)null)
				{
					return;
				}
				HashSet<ZDOID> hashSet = new HashSet<ZDOID>();
				foreach (SummonRegistry.Summon item in SummonRegistry.Owned)
				{
					if (!SummonRegistry.Usable(item))
					{
						continue;
					}
					hashSet.Add(item.Id);
					if (Pins.TryGetValue(item.Id, out var value))
					{
						value.m_pos = ((Component)item.Character).transform.position;
						ApplyStyle(value);
						continue;
					}
					PinData val = Minimap.instance.AddPin(((Component)item.Character).transform.position, SkeletonCrewPlugin.MapPinType.Value, SkeletonCrewPlugin.ShowNamesOnMap.Value ? item.Character.GetHoverName() : string.Empty, false, false, 0L, default(PlatformUserID));
					if (val != null)
					{
						ApplyStyle(val);
						Pins[item.Id] = val;
					}
				}
				if (Pins.Count == hashSet.Count)
				{
					return;
				}
				List<ZDOID> list = new List<ZDOID>();
				foreach (KeyValuePair<ZDOID, PinData> pin in Pins)
				{
					if (!hashSet.Contains(pin.Key))
					{
						list.Add(pin.Key);
					}
				}
				foreach (ZDOID item2 in list)
				{
					Remove(item2);
				}
			}
		}

		private static void ApplyStyle(PinData pin)
		{
			pin.m_doubleSize = SkeletonCrewPlugin.MapPinDoubleSize.Value;
			pin.m_animate = SkeletonCrewPlugin.MapPinAnimate.Value;
		}

		private static void Remove(ZDOID id)
		{
			//IL_0005: 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)
			if (Pins.TryGetValue(id, out var value))
			{
				if ((Object)(object)Minimap.instance != (Object)null)
				{
					Minimap.instance.RemovePin(value);
				}
				Pins.Remove(id);
			}
		}

		internal static void Clear()
		{
			foreach (KeyValuePair<ZDOID, PinData> pin in Pins)
			{
				if ((Object)(object)Minimap.instance != (Object)null)
				{
					Minimap.instance.RemovePin(pin.Value);
				}
			}
			Pins.Clear();
		}
	}
	[BepInPlugin("com.vash.skeletoncrew", "SkeletonCrew", "1.0.2")]
	[BepInProcess("valheim.exe")]
	public class SkeletonCrewPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.vash.skeletoncrew";

		public const string PluginName = "SkeletonCrew";

		public const string PluginVersion = "1.0.2";

		private static readonly Dictionary<SummonPreference, ConfigEntry<float>> HealthScales = new Dictionary<SummonPreference, ConfigEntry<float>>();

		private static readonly Dictionary<SummonPreference, ConfigEntry<float>> DamageScales = new Dictionary<SummonPreference, ConfigEntry<float>>();

		private static readonly Dictionary<SummonPreference, ConfigEntry<float>> ResistScales = new Dictionary<SummonPreference, ConfigEntry<float>>();

		private const float TickInterval = 0.5f;

		private Harmony _harmony;

		private float _nextTick;

		private float _lastTick;

		private int _errorCount;

		private float _lastErrorLog = -999f;

		internal static ManualLogSource Log { get; private set; }

		internal static SkeletonCrewPlugin Instance { get; private set; }

		internal static ConfigEntry<bool> Enabled { get; private set; }

		internal static ConfigEntry<bool> VerboseLogging { get; private set; }

		internal static ConfigEntry<string> SummonPrefabPatterns { get; private set; }

		internal static ConfigEntry<bool> TraceOrders { get; private set; }

		internal static ConfigEntry<bool> DeepTrace { get; private set; }

		internal static ConfigEntry<float> DeepTraceInterval { get; private set; }

		internal static ConfigEntry<float> RegenPercentPerSecond { get; private set; }

		internal static ConfigEntry<bool> HarvestEnabled { get; private set; }

		internal static ConfigEntry<bool> HarvestTrees { get; private set; }

		internal static ConfigEntry<bool> HarvestRock { get; private set; }

		internal static ConfigEntry<bool> HarvestDestructibles { get; private set; }

		internal static ConfigEntry<bool> HarvestPickables { get; private set; }

		internal static ConfigEntry<bool> HarvestContinue { get; private set; }

		internal static ConfigEntry<float> HarvestReach { get; private set; }

		internal static ConfigEntry<float> HarvestSettleSeconds { get; private set; }

		internal static ConfigEntry<float> HarvestLogSearchRadius { get; private set; }

		internal static ConfigEntry<bool> HarvestStructures { get; private set; }

		internal static ConfigEntry<bool> ProtectPlayerBase { get; private set; }

		internal static ConfigEntry<float> HealthBloodMagicBonus { get; private set; }

		internal static ConfigEntry<float> HarvestAreaRadius { get; private set; }

		internal static ConfigEntry<int> HarvestAreasPerWorker { get; private set; }

		internal static ConfigEntry<float> HarvestReachVertical { get; private set; }

		internal static ConfigEntry<float> HarvestStallSeconds { get; private set; }

		internal static ConfigEntry<float> HarvestSwingSeconds { get; private set; }

		internal static ConfigEntry<float> HarvestDamage { get; private set; }

		internal static ConfigEntry<SummonPreference> SummonWeaponPreference { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> MenuKey { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> CycleSummonTypeKey { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> SelectionKey { get; private set; }

		internal static ConfigEntry<bool> EnableAdaptive { get; private set; }

		internal static ConfigEntry<string> ClassMeleeItems { get; private set; }

		internal static ConfigEntry<string> ClassArcherItems { get; private set; }

		internal static ConfigEntry<string> ClassDefenderItems { get; private set; }

		internal static ConfigEntry<string> ClassHealerItems { get; private set; }

		internal static ConfigEntry<string> ClassFireMageItems { get; private set; }

		internal static ConfigEntry<string> ClassIceMageItems { get; private set; }

		internal static ConfigEntry<string> ClassMeleeAnimation { get; private set; }

		internal static ConfigEntry<string> ClassArcherAnimation { get; private set; }

		internal static ConfigEntry<string> ClassDefenderAnimation { get; private set; }

		internal static ConfigEntry<string> ClassHealerAnimation { get; private set; }

		internal static ConfigEntry<string> ClassFireMageAnimation { get; private set; }

		internal static ConfigEntry<string> ClassIceMageAnimation { get; private set; }

		internal static ConfigEntry<string> ClassHealerAttackFrom { get; private set; }

		internal static ConfigEntry<string> ClassFireMageAttackFrom { get; private set; }

		internal static ConfigEntry<string> ClassIceMageAttackFrom { get; private set; }

		internal static ConfigEntry<float> ClassMeleeRange { get; private set; }

		internal static ConfigEntry<float> ClassArcherRange { get; private set; }

		internal static ConfigEntry<float> ClassDefenderRange { get; private set; }

		internal static ConfigEntry<float> ClassHealerRange { get; private set; }

		internal static ConfigEntry<float> ClassFireMageRange { get; private set; }

		internal static ConfigEntry<float> ClassIceMageRange { get; private set; }

		internal static ConfigEntry<string> ClassDefenderUnlock { get; private set; }

		internal static ConfigEntry<string> ClassHealerUnlock { get; private set; }

		internal static ConfigEntry<string> ClassFireMageUnlock { get; private set; }

		internal static ConfigEntry<string> ClassIceMageUnlock { get; private set; }

		internal static ConfigEntry<float> ProgressionBonusPerUnlock { get; private set; }

		internal static ConfigEntry<int> ClassMeleeLimit { get; private set; }

		internal static ConfigEntry<int> ClassArcherLimit { get; private set; }

		internal static ConfigEntry<int> ClassDefenderLimit { get; private set; }

		internal static ConfigEntry<int> ClassHealerLimit { get; private set; }

		internal static ConfigEntry<int> ClassFireMageLimit { get; private set; }

		internal static ConfigEntry<int> ClassIceMageLimit { get; private set; }

		internal static ConfigEntry<string> SummonPresets { get; private set; }

		internal static ConfigEntry<float> GroupCostPerExtra { get; private set; }

		internal static ConfigEntry<float> HealerFormationScale { get; private set; }

		internal static ConfigEntry<float> LavaEscapeSeconds { get; private set; }

		internal static ConfigEntry<float> LavaRescueSeconds { get; private set; }

		internal static ConfigEntry<bool> RoleFormation { get; private set; }

		internal static ConfigEntry<float> FrontLineRadiusScale { get; private set; }

		internal static ConfigEntry<float> BackLineRadiusScale { get; private set; }

		internal static ConfigEntry<float> BackLineEngageDistance { get; private set; }

		internal static ConfigEntry<float> BackLineScreenDistance { get; private set; }

		internal static ConfigEntry<float> BackLineFleeHealth { get; private set; }

		internal static ConfigEntry<float> FrontLineViewMultiplier { get; private set; }

		internal static ConfigEntry<float> FrontLineLeashScale { get; private set; }

		internal static ConfigEntry<bool> HealerHealsPlayers { get; private set; }

		internal static ConfigEntry<float> HealerHealRadius { get; private set; }

		internal static ConfigEntry<float> HealerWardInterval { get; private set; }

		internal static ConfigEntry<float> HealerWardRadius { get; private set; }

		internal static ConfigEntry<float> HealerWardSeconds { get; private set; }

		internal static ConfigEntry<bool> DevotionScaling { get; private set; }

		internal static ConfigEntry<float> DevotionFloor { get; private set; }

		internal static ConfigEntry<float> DevotionFullGear { get; private set; }

		internal static ConfigEntry<float> DevotionFullArsenal { get; private set; }

		internal static ConfigEntry<float> WardApproachRadius { get; private set; }

		internal static ConfigEntry<float> HealerCriticalHealth { get; private set; }

		internal static ConfigEntry<float> HealerEmergencyInterval { get; private set; }

		internal static ConfigEntry<float> HealerCastHealPercent { get; private set; }

		internal static ConfigEntry<float> PressureWindowSeconds { get; private set; }

		internal static ConfigEntry<float> HealerRescueHealth { get; private set; }

		internal static ConfigEntry<float> HealerHealThreshold { get; private set; }

		internal static ConfigEntry<bool> HealerCastsStaff { get; private set; }

		internal static ConfigEntry<float> HealerCastInterval { get; private set; }

		internal static ConfigEntry<float> HealerCastHealAmount { get; private set; }

		internal static ConfigEntry<float> HealerCastHealRadius { get; private set; }

		internal static ConfigEntry<bool> MoveEndsInHold { get; private set; }

		internal static ConfigEntry<float> PreciseHoldSlack { get; private set; }

		internal static ConfigEntry<bool> AvoidLava { get; private set; }

		internal static ConfigEntry<float> LavaLookahead { get; private set; }

		internal static ConfigEntry<float> LavaCrossingTolerance { get; private set; }

		internal static ConfigEntry<bool> LavaDodge { get; private set; }

		internal static ConfigEntry<bool> FocusFire { get; private set; }

		internal static ConfigEntry<float> HazardMemorySeconds { get; private set; }

		internal static ConfigEntry<float> HazardSettleSeconds { get; private set; }

		internal static ConfigEntry<float> RouteDetourFactor { get; private set; }

		internal static ConfigEntry<bool> MarchingOrder { get; private set; }

		internal static ConfigEntry<float> MarchSlack { get; private set; }

		internal static ConfigEntry<bool> PullTactics { get; private set; }

		internal static ConfigEntry<float> PullReceiveDistance { get; private set; }

		internal static ConfigEntry<float> PullTimeoutSeconds { get; private set; }

		internal static ConfigEntry<bool> AllowDismiss { get; private set; }

		internal static ConfigEntry<bool> AttackInWater { get; private set; }

		internal static ConfigEntry<bool> NoPlayerCollision { get; private set; }

		internal static ConfigEntry<bool> AdjustAttackGeometry { get; private set; }

		internal static ConfigEntry<float> AttackHeight { get; private set; }

		internal static ConfigEntry<float> AttackCharExtra { get; private set; }

		internal static ConfigEntry<float> AttackRange { get; private set; }

		internal static ConfigEntry<float> AttackRayWidth { get; private set; }

		internal static ConfigEntry<float> AttackAngle { get; private set; }

		internal static ConfigEntry<CrewStance> StanceSetting { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> StanceKey { get; private set; }

		internal static ConfigEntry<float> OffensiveViewMultiplier { get; private set; }

		internal static ConfigEntry<float> OffensiveReachMultiplier { get; private set; }

		internal static ConfigEntry<float> DefensiveReachMultiplier { get; private set; }

		internal static ConfigEntry<float> ChaseLeash { get; private set; }

		internal static ConfigEntry<float> DefensiveLeash { get; private set; }

		internal static ConfigEntry<bool> GuardTheOwner { get; private set; }

		internal static ConfigEntry<float> GuardPerimeterRadius { get; private set; }

		internal static ConfigEntry<bool> SmartWeaponChoice { get; private set; }

		internal static ConfigEntry<bool> ReplaceWeakestSummon { get; private set; }

		internal static ConfigEntry<int> SummonCapBonus { get; private set; }

		internal static ConfigEntry<int> SummonCapBonusAtLevel { get; private set; }

		internal static ConfigEntry<float> SummonEitrCostMultiplier { get; private set; }

		internal static ConfigEntry<float> SummonHealthCostMultiplier { get; private set; }

		internal static ConfigEntry<float> MeleeSwitchDistance { get; private set; }

		internal static ConfigEntry<float> RangedSwitchDistance { get; private set; }

		internal static ConfigEntry<float> WeaponSwapSeconds { get; private set; }

		internal static ConfigEntry<float> FriendlyFireConeDegrees { get; private set; }

		internal static ConfigEntry<bool> ArchersKeepDistance { get; private set; }

		internal static ConfigEntry<float> KiteDistance { get; private set; }

		internal static ConfigEntry<float> KiteInterval { get; private set; }

		internal static ConfigEntry<float> KiteDuration { get; private set; }

		internal static ConfigEntry<bool> DefendInterruptsWork { get; private set; }

		internal static ConfigEntry<float> DefendRadius { get; private set; }

		internal static ConfigEntry<float> WorkResumeSeconds { get; private set; }

		internal static ConfigEntry<float> ElementalResistAtMaxSkill { get; private set; }

		internal static ConfigEntry<float> PhysicalResistAtMaxSkill { get; private set; }

		internal static ConfigEntry<float> ShieldAbsorbBonusAtMaxSkill { get; private set; }

		internal static ConfigEntry<float> DamageBonusAtMaxSkill { get; private set; }

		internal static ConfigEntry<float> RegenBloodMagicBonus { get; private set; }

		internal static ConfigEntry<float> RegenOutOfCombatSeconds { get; private set; }

		internal static ConfigEntry<bool> ShowCrewHud { get; private set; }

		internal static ConfigEntry<float> CrewHudX { get; private set; }

		internal static ConfigEntry<float> CrewHudY { get; private set; }

		internal static ConfigEntry<float> CrewHudScale { get; private set; }

		internal static ConfigEntry<bool> ShowRegenText { get; private set; }

		internal static ConfigEntry<bool> ShowSummonGlow { get; private set; }

		internal static ConfigEntry<string> GlowColour { get; private set; }

		internal static ConfigEntry<string> GlowSelectedColour { get; private set; }

		internal static ConfigEntry<float> GlowIntensity { get; private set; }

		internal static ConfigEntry<float> GlowRange { get; private set; }

		internal static ConfigEntry<float> GlowHeight { get; private set; }

		internal static ConfigEntry<string> MarkerEffectPrefab { get; private set; }

		internal static ConfigEntry<float> RegenTextInterval { get; private set; }

		internal static ConfigEntry<float> RegenTextMinimum { get; private set; }

		internal static ConfigEntry<bool> EnableVanillaCommands { get; private set; }

		internal static ConfigEntry<bool> AutoFollowOnSummon { get; private set; }

		internal static ConfigEntry<bool> ShowOrderMessages { get; private set; }

		internal static ConfigEntry<float> CommandRadius { get; private set; }

		internal static ConfigEntry<float> TargetRange { get; private set; }

		internal static ConfigEntry<float> TargetAssistRadius { get; private set; }

		internal static ConfigEntry<bool> RecallEnabled { get; private set; }

		internal static ConfigEntry<float> RecallDistance { get; private set; }

		internal static ConfigEntry<float> RecallStuckDistance { get; private set; }

		internal static ConfigEntry<float> RecallStuckSeconds { get; private set; }

		internal static ConfigEntry<float> RecallElevation { get; private set; }

		internal static ConfigEntry<float> RecallElevationSeconds { get; private set; }

		internal static ConfigEntry<float> RecallStrandedDistance { get; private set; }

		internal static ConfigEntry<float> RecallSpread { get; private set; }

		internal static ConfigEntry<float> RecallGraceSeconds { get; private set; }

		internal static ConfigEntry<bool> TeleportSummons { get; private set; }

		internal static ConfigEntry<int> MaxTeleportSummons { get; private set; }

		internal static ConfigEntry<float> EscortRadius { get; private set; }

		internal static ConfigEntry<float> SpeedMultiplier { get; private set; }

		internal static ConfigEntry<bool> FormUpWhenIdle { get; private set; }

		internal static ConfigEntry<float> FollowFormationRadius { get; private set; }

		internal static ConfigEntry<float> FormUpDelaySeconds { get; private set; }

		internal static ConfigEntry<float> FollowDriveDistance { get; private set; }

		internal static ConfigEntry<bool> MatchPlayerRunSpeed { get; private set; }

		internal static ConfigEntry<float> CatchUpMargin { get; private set; }

		internal static ConfigEntry<bool> UseCustomAgent { get; private set; }

		internal static ConfigEntry<float> SummonAgentClimb { get; private set; }

		internal static ConfigEntry<float> AutoJumpInterval { get; private set; }

		internal static ConfigEntry<bool> DriveOrderedMovement { get; private set; }

		internal static ConfigEntry<bool> RunOnOrders { get; private set; }

		internal static ConfigEntry<bool> StepAssistEnabled { get; private set; }

		internal static ConfigEntry<float> StepAssistStallSeconds { get; private set; }

		internal static ConfigEntry<float> StepAssistCooldown { get; private set; }

		internal static ConfigEntry<float> StepAssistMinDistance { get; private set; }

		internal static ConfigEntry<bool> ShowOnMap { get; private set; }

		internal static ConfigEntry<bool> ShowNamesOnMap { get; private set; }

		internal static ConfigEntry<PinType> MapPinType { get; private set; }

		internal static ConfigEntry<bool> MapPinDoubleSize { get; private set; }

		internal static ConfigEntry<bool> MapPinAnimate { get; private set; }

		internal static ConfigEntry<float> TeleportGuardSeconds { get; private set; }

		internal static ConfigEntry<KeyboardShortcut> CommandButton { get; private set; }

		internal static ConfigEntry<float> AttackOrderSeconds { get; private set; }

		internal static ConfigEntry<float> MoveOrderSeconds { get; private set; }

		internal static ConfigEntry<float> MoveArriveDistance { get; private set; }

		internal static ConfigEntry<float> MoveSpread { get; private set; }

		internal static ConfigEntry<float> MultiTapSeconds { get; private set; }

		internal static ConfigEntry<float> GuardRadius { get; private set; }

		internal static ConfigEntry<bool> GuardPatrol { get; private set; }

		internal static ConfigEntry<float> GuardPatrolRadius { get; private set; }

		internal static ConfigEntry<float> GuardPatrolInterval { get; private set; }

		internal static ConfigEntry<bool> OrdersOverrideCombat { get; private set; }

		internal static ConfigEntry<float> ObeySeconds { get; private set; }

		internal static ConfigEntry<float> RegroupDistance { get; private set; }

		internal static ConfigEntry<string> ClassItems(SummonPreference pref)
		{
			return (ConfigEntry<string>)(pref switch
			{
				SummonPreference.Melee => ClassMeleeItems, 
				SummonPreference.Archer => ClassArcherItems, 
				SummonPreference.Defender => ClassDefenderItems, 
				SummonPreference.Healer => ClassHealerItems, 
				SummonPreference.FireMage => ClassFireMageItems, 
				SummonPreference.IceMage => ClassIceMageItems, 
				_ => null, 
			});
		}

		internal static ConfigEntry<string> ClassAnimation(SummonPreference pref)
		{
			return (ConfigEntry<string>)(pref switch
			{
				SummonPreference.Melee => ClassMeleeAnimation, 
				SummonPreference.Archer => ClassArcherAnimation, 
				SummonPreference.Defender => ClassDefenderAnimation, 
				SummonPreference.Healer => ClassHealerAnimation, 
				SummonPreference.FireMage => ClassFireMageAnimation, 
				SummonPreference.IceMage => ClassIceMageAnimation, 
				_ => null, 
			});
		}

		private ConfigEntry<string> BindClassItems(string className, string items, string note)
		{
			return ((BaseUnityPlugin)this).Config.Bind<string>("Classes", className + "Items", items, "Item prefabs this class is raised with, comma-separated. " + note);
		}

		internal static ConfigEntry<string> ClassAttackFrom(SummonPreference pref)
		{
			return (ConfigEntry<string>)(pref switch
			{
				SummonPreference.Healer => ClassHealerAttackFrom, 
				SummonPreference.FireMage => ClassFireMageAttackFrom, 
				SummonPreference.IceMage => ClassIceMageAttackFrom, 
				_ => null, 
			});
		}

		private ConfigEntry<string> BindClassAttackFrom(string className, string donor)
		{
			return ((BaseUnityPlugin)this).Config.Bind<string>("Classes", className + "AttackFrom", donor, "Item prefab whose ATTACK this class borrows - the projectile, damage and effect - while holding the weapon named in " + className + "Items. Empty means keep the weapon's own attack. This exists because the creature staves that cast correctly have no model at all, so a summon holding one appears empty-handed.");
		}

		internal static ConfigEntry<int> ClassLimit(SummonPreference pref)
		{
			return (ConfigEntry<int>)(pref switch
			{
				SummonPreference.Melee => ClassMeleeLimit, 
				SummonPreference.Archer => ClassArcherLimit, 
				SummonPreference.Defender => ClassDefenderLimit, 
				SummonPreference.Healer => ClassHealerLimit, 
				SummonPreference.FireMage => ClassFireMageLimit, 
				SummonPreference.IceMage => ClassIceMageLimit, 
				_ => null, 
			});
		}

		private ConfigEntry<int> BindClassLimit(string className, int limit)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			return ((BaseUnityPlugin)this).Config.Bind<int>("Classes", className + "Limit", limit, new ConfigDescription("How many " + className + " summons may exist at once. 0 means no limit of its own, so the crew cap is the only ceiling. At the limit the next raise becomes a warrior, with a notice, rather than costing you the Eitr for nothing.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 12), Array.Empty<object>()));
		}

		internal static ConfigEntry<float> ClassHealthScale(SummonPreference pref)
		{
			if (!HealthScales.TryGetValue(pref, out var value))
			{
				return null;
			}
			return value;
		}

		internal static ConfigEntry<float> ClassDamageScale(SummonPreference pref)
		{
			if (!DamageScales.TryGetValue(pref, out var value))
			{
				return null;
			}
			return value;
		}

		internal static ConfigEntry<float> ClassResistScale(SummonPreference pref)
		{
			if (!ResistScales.TryGetValue(pref, out var value))
			{
				return null;
			}
			return value;
		}

		private void BindClassStats(SummonPreference pref, float health, float damage, float resist)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			string text = pref.ToString();
			HealthScales[pref] = ((BaseUnityPlugin)this).Config.Bind<float>("Classes", text + "HealthScale", health, new ConfigDescription("Maximum health for a " + text + ", as a multiple of what the crew-wide Blood Magic scaling already gives. 1 is no difference.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 4f), Array.Empty<object>()));
			DamageScales[pref] = ((BaseUnityPlugin)this).Config.Bind<float>("Classes", text + "DamageScale", damage, new ConfigDescription("Damage a " + text + " deals, as a multiple of the crew-wide scaling.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 4f), Array.Empty<object>()));
			ResistScales[pref] = ((BaseUnityPlugin)this).Config.Bind<float>("Classes", text + "ResistScale", resist, new ConfigDescription("How much of the crew-wide damage REDUCTION a " + text + " gets. Above 1 means it takes less than the rest of the crew; below 1, more.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 4f), Array.Empty<object>()));
		}

		internal static ConfigEntry<float> ClassRange(SummonPreference pref)
		{
			return (ConfigEntry<float>)(pref switch
			{
				SummonPreference.Melee => ClassMeleeRange, 
				SummonPreference.Archer => ClassArcherRange, 
				SummonPreference.Defender => ClassDefenderRange, 
				SummonPreference.Healer => ClassHealerRange, 
				SummonPreference.FireMage => ClassFireMageRange, 
				SummonPreference.IceMage => ClassIceMageRange, 
				_ => null, 
			});
		}

		internal static ConfigEntry<string> ClassUnlock(SummonPreference pref)
		{
			return (ConfigEntry<string>)(pref switch
			{
				SummonPreference.Defender => ClassDefenderUnlock, 
				SummonPreference.Healer => ClassHealerUnlock, 
				SummonPreference.FireMage => ClassFireMageUnlock, 
				SummonPreference.IceMage => ClassIceMageUnlock, 
				_ => null, 
			});
		}

		private ConfigEntry<float> BindClassRange(string className)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			return ((BaseUnityPlugin)this).Config.Bind<float>("Classes", className + "Range", 0f, new ConfigDescription("Attack range this class uses its weapon from, in metres. 0 keeps the weapon's own. Creature weapons are tuned for the creature that owns them - the Dverger heal staff assumes a Dverger in its own formation, not a summon trailing you - so a healer that barely reaches anyone is fixed here.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>()));
		}

		private ConfigEntry<string> BindClassUnlock(string className, string prefab)
		{
			return ((BaseUnityPlugin)this).Config.Bind<string>("Classes", className + "Unlock", prefab, "Item prefab that unlocks this class - it becomes available once you have HELD one. Empty means always available. Named as a prefab like the rest of this section; the translation to the game's internal key is done for you.");
		}

		private ConfigEntry<string> BindClassAnimation(string className, string animation)
		{
			return ((BaseUnityPlugin)this).Config.Bind<string>("Classes", className + "Animation", animation, "Attack animation to force on this class's weapons. A summon can only play the animations its OWN weapons use - 'attack' and 'attack_bow' - so any staff needs rebinding or it will equip, take a target and never swing. Empty leaves the weapon as the game shipped it.");
		}

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Invalid comparison between Unknown and I4
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Expected O, but got Unknown
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Expected O, but got Unknown
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Expected O, but got Unknown
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Expected O, but got Unknown
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Expected O, but got Unknown
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Expected O, but got Unknown
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Expected O, but got Unknown
			//IL_03b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bb: Expected O, but got Unknown
			//IL_06e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06eb: Expected O, but got Unknown
			//IL_071e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0728: Expected O, but got Unknown
			//IL_075b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0765: Expected O, but got Unknown
			//IL_0798: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a2: Expected O, but got Unknown
			//IL_07f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ff: Expected O, but got Unknown
			//IL_0832: Unknown result type (might be due to invalid IL or missing references)
			//IL_083c: Expected O, but got Unknown
			//IL_086f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0879: Expected O, but got Unknown
			//IL_08ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_08b6: Expected O, but got Unknown
			//IL_08e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f3: Expected O, but got Unknown
			//IL_0926: Unknown result type (might be due to invalid IL or missing references)
			//IL_0930: Expected O, but got Unknown
			//IL_0963: Unknown result type (might be due to invalid IL or missing references)
			//IL_096d: Expected O, but got Unknown
			//IL_09c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ca: Expected O, but got Unknown
			//IL_0a1d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a27: Expected O, but got Unknown
			//IL_0a5a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a64: Expected O, but got Unknown
			//IL_0a97: Unknown result type (might be due to invalid IL or missing references)
			//IL_0aa1: Expected O, but got Unknown
			//IL_0ad4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ade: Expected O, but got Unknown
			//IL_0b11: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b1b: Expected O, but got Unknown
			//IL_0b4e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b58: Expected O, but got Unknown
			//IL_0b8b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b95: Expected O, but got Unknown
			//IL_0bc8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bd2: Expected O, but got Unknown
			//IL_0c05: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c0f: Expected O, but got Unknown
			//IL_0c42: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c4c: Expected O, but got Unknown
			//IL_0c7f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c89: Expected O, but got Unknown
			//IL_0cbc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cc6: Expected O, but got Unknown
			//IL_0d19: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d23: Expected O, but got Unknown
			//IL_0d56: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d60: Expected O, but got Unknown
			//IL_0d93: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d9d: Expected O, but got Unknown
			//IL_0dd0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0dda: Expected O, but got Unknown
			//IL_0e77: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ea5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f07: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f11: Expected O, but got Unknown
			//IL_0f44: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f4e: Expected O, but got Unknown
			//IL_0fc1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0fcb: Expected O, but got Unknown
			//IL_0ffe: Unknown result type (might be due to invalid IL or missing references)
			//IL_1008: Expected O, but got Unknown
			//IL_103b: Unknown result type (might be due to invalid IL or missing references)
			//IL_1045: Expected O, but got Unknown
			//IL_1078: Unknown result type (might be due to invalid IL or missing references)
			//IL_1082: Expected O, but got Unknown
			//IL_10d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_10df: Expected O, but got Unknown
			//IL_1132: Unknown result type (might be due to invalid IL or missing references)
			//IL_113c: Expected O, but got Unknown
			//IL_116f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1179: Expected O, but got Unknown
			//IL_11ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_11b6: Expected O, but got Unknown
			//IL_11f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_12b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_12c1: Expected O, but got Unknown
			//IL_12f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_12fe: Expected O, but got Unknown
			//IL_1331: Unknown result type (might be due to invalid IL or missing references)
			//IL_133b: Expected O, but got Unknown
			//IL_1377: Unknown result type (might be due to invalid IL or missing references)
			//IL_13b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_13c3: Expected O, but got Unknown
			//IL_13f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_1400: Expected O, but got Unknown
			//IL_1433: Unknown result type (might be due to invalid IL or missing references)
			//IL_143d: Expected O, but got Unknown
			//IL_1470: Unknown result type (might be due to invalid IL or missing references)
			//IL_147a: Expected O, but got Unknown
			//IL_14ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_14b7: Expected O, but got Unknown
			//IL_150a: Unknown result type (might be due to invalid IL or missing references)
			//IL_1514: Expected O, but got Unknown
			//IL_1547: Unknown result type (might be due to invalid IL or missing references)
			//IL_1551: Expected O, but got Unknown
			//IL_1584: Unknown result type (might be due to invalid IL or missing references)
			//IL_158e: Expected O, but got Unknown
			//IL_15b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_15c0: Expected O, but got Unknown
			//IL_15e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_15f2: Expected O, but got Unknown
			//IL_1665: Unknown result type (might be due to invalid IL or missing references)
			//IL_166f: Expected O, but got Unknown
			//IL_16a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_16ac: Expected O, but got Unknown
			//IL_16df: Unknown result type (might be due to invalid IL or missing references)
			//IL_16e9: Expected O, but got Unknown
			//IL_171c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1726: Expected O, but got Unknown
			//IL_1779: Unknown result type (might be due to invalid IL or missing references)
			//IL_1783: Expected O, but got Unknown
			//IL_17b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_17c0: Expected O, but got Unknown
			//IL_17f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_17fd: Expected O, but got Unknown
			//IL_1850: Unknown result type (might be due to invalid IL or missing references)
			//IL_185a: Expected O, but got Unknown
			//IL_188d: Unknown result type (might be due to invalid IL or missing references)
			//IL_1897: Expected O, but got Unknown
			//IL_18ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_18d4: Expected O, but got Unknown
			//IL_1907: Unknown result type (might be due to invalid IL or missing references)
			//IL_1911: Expected O, but got Unknown
			//IL_1944: Unknown result type (might be due to invalid IL or missing references)
			//IL_194e: Expected O, but got Unknown
			//IL_1981: Unknown result type (might be due to invalid IL or missing references)
			//IL_198b: Expected O, but got Unknown
			//IL_19be: Unknown result type (might be due to invalid IL or missing references)
			//IL_19c8: Expected O, but got Unknown
			//IL_19fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_1a05: Expected O, but got Unknown
			//IL_1a38: Unknown result type (might be due to invalid IL or missing references)
			//IL_1a42: Expected O, but got Unknown
			//IL_1a75: Unknown result type (might be due to invalid IL or missing references)
			//IL_1a7f: Expected O, but got Unknown
			//IL_1ab2: Unknown result type (might be due to invalid IL or missing references)
			//IL_1abc: Expected O, but got Unknown
			//IL_1b0f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1b19: Expected O, but got Unknown
			//IL_1b4c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1b56: Expected O, but got Unknown
			//IL_1b89: Unknown result type (might be due to invalid IL or missing references)
			//IL_1b93: Expected O, but got Unknown
			//IL_1c2e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1c38: Expected O, but got Unknown
			//IL_1c6b: Unknown result type (might be due to invalid IL or missing references)
			//IL_1c75: Expected O, but got Unknown
			//IL_1ca8: Unknown result type (might be due to invalid IL or missing references)
			//IL_1cb2: Expected O, but got Unknown
			//IL_1d29: Unknown result type (might be due to invalid IL or missing references)
			//IL_1d33: Expected O, but got Unknown
			//IL_1d66: Unknown result type (might be due to invalid IL or missing references)
			//IL_1d70: Expected O, but got Unknown
			//IL_1dc3: Unknown result type (might be due to invalid IL or missing references)
			//IL_1dcd: Expected O, but got Unknown
			//IL_1ea4: Unknown result type (might be due to invalid IL or missing references)
			//IL_1eae: Expected O, but got Unknown
			//IL_1ee1: Unknown result type (might be due to invalid IL or missing references)
			//IL_1eeb: Expected O, but got Unknown
			//IL_1f1e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1f28: Expected O, but got Unknown
			//IL_1f5b: Unknown result type (might be due to invalid IL or missing references)
			//IL_1f65: Expected O, but got Unknown
			//IL_1fb8: Unknown result type (might be due to invalid IL or missing references)
			//IL_1fc2: Expected O, but got Unknown
			//IL_1ff5: Unknown result type (might be due to invalid IL or missing references)
			//IL_1fff: Expected O, but got Unknown
			//IL_2032: Unknown result type (might be due to invalid IL or missing references)
			//IL_203c: Expected O, but got Unknown
			//IL_208f: Unknown result type (might be due to invalid IL or missing references)
			//IL_2099: Expected O, but got Unknown
			//IL_20ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_20f6: Expected O, but got Unknown
			//IL_2129: Unknown result type (might be due to invalid IL or missing references)
			//IL_2133: Expected O, but got Unknown
			//IL_21c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_21d0: Expected O, but got Unknown
			//IL_2203: Unknown result type (might be due to invalid IL or missing references)
			//IL_220d: Expected O, but got Unknown
			//IL_2240: Unknown result type (might be due to invalid IL or missing references)
			//IL_224a: Expected O, but got Unknown
			//IL_233d: Unknown result type (might be due to invalid IL or missing references)
			//IL_2347: Expected O, but got Unknown
			//IL_239a: Unknown result type (might be due to invalid IL or missing references)
			//IL_23a4: Expected O, but got Unknown
			//IL_23cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_23d7: Expected O, but got Unknown
			//IL_240a: Unknown result type (might be due to invalid IL or missing references)
			//IL_2414: Expected O, but got Unknown
			//IL_2447: Unknown result type (might be due to invalid IL or missing references)
			//IL_2451: Expected O, but got Unknown
			//IL_2484: Unknown result type (might be due to invalid IL or missing references)
			//IL_248e: Expected O, but got Unknown
			//IL_24c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_24cb: Expected O, but got Unknown
			//IL_24fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_2508: Expected O, but got Unknown
			//IL_253b: Unknown result type (might be due to invalid IL or missing references)
			//IL_2545: Expected O, but got Unknown
			//IL_2578: Unknown result type (might be due to invalid IL or missing references)
			//IL_2582: Expected O, but got Unknown
			//IL_25b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_25bf: Expected O, but got Unknown
			//IL_25db: Unknown result type (might be due to invalid IL or missing references)
			//IL_261d: Unknown result type (might be due to invalid IL or missing references)
			//IL_2627: Expected O, but got Unknown
			//IL_265a: Unknown result type (might be due to invalid IL or missing references)
			//IL_2664: Expected O, but got Unknown
			//IL_2697: Unknown result type (might be due to invalid IL or missing references)
			//IL_26a1: Expected O, but got Unknown
			//IL_26d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_26de: Expected O, but got Unknown
			//IL_2711: Unknown result type (might be due to invalid IL or missing references)
			//IL_271b: Expected O, but got Unknown
			//IL_276e: Unknown result type (might be due to invalid IL or missing references)
			//IL_2778: Expected O, but got Unknown
			//IL_27ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_27b5: Expected O, but got Unknown
			//IL_27e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_27f2: Expected O, but got Unknown
			//IL_2845: Unknown result type (might be due to invalid IL or missing references)
			//IL_284f: Expected O, but got Unknown
			//IL_2882: Unknown result type (might be due to invalid IL or missing references)
			//IL_288c: Expected O, but got Unknown
			//IL_28a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_28ac: Expected O, but got Unknown
			//IL_28da: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			if ((int)SystemInfo.graphicsDeviceType == 4)
			{
				Log.LogInfo((object)"Headless process - SkeletonCrew disabled.");
				return;
			}
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. When false nothing is patched or modified.");
			VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLogging", false, "Developer logging: a breakdown of every summon discovered (components, unsummon distance, what it holds and whether the game can draw it), plus leash, escort, recall and loadout detail. Roughly 60 lines a minute with a full crew, so it is off unless you are diagnosing something.");
			RegenPercentPerSecond = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "PercentOfMaxPerSecond", 1f, new ConfigDescription("Base health regenerated per second, as a percent of the summon's max health, before Blood Magic scaling. 0 disables regen entirely.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			HarvestEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Harvest", "Enabled", false, "Master switch for harvesting. With this off, summons never target trees, ore or destructibles at all and the command button keeps its combat/move meanings.");
			HarvestTrees = ((BaseUnityPlugin)this).Config.Bind<bool>("Harvest", "Trees", true, "Allow felling trees and chopping the logs they leave.");
			HarvestRock = ((BaseUnityPlugin)this).Config.Bind<bool>("Harvest", "OreAndRock", true, "Allow mining ore nodes and rocks.");
			HarvestDestructibles = ((BaseUnityPlugin)this).Config.Bind<bool>("Harvest", "Destructibles", true, "Allow breaking stumps, small rocks and similar. Player buildings use WearNTear and are never targetable.");
			HarvestPickables = ((BaseUnityPlugin)this).Config.Bind<bool>("Harvest", "Pickables", false, "Let summons PICK berries, mushrooms and thistle for you. These are never destroyed either way - they respawn, so smashing one would lose the resource permanently. With this off they are simply ignored.");
			HarvestContinue = ((BaseUnityPlugin)this).Config.Bind<bool>("Harvest", "ContinueNearby", true, "After finishing, move to the next target of the SAME kind within the radius, so one order clears a copse.");
			HarvestSettleSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Harvest", "SettleSeconds", 1f, new ConfigDescription("Pause after finishing a target before looking for the next. A felled tree's log spawns as the trunk dies, so searching immediately finds the stump instead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
			HarvestLogSearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Harvest", "LogSearchRadius", 12f, new ConfigDescription("How far from a felled tree to look for the log it dropped. Big trees fall some distance from their stump.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 40f), Array.Empty<object>()));
			HarvestReach = ((BaseUnityPlugin)this).Config.Bind<float>("Harvest", "Reach", 3.5f, new ConfigDescription("How close a summon must be to work its target.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1.5f, 10f), Array.Empty<object>()));
			ProtectPlayerBase = ((BaseUnityPlugin)this).Config.Bind<bool>("Harvest", "ProtectPlayerBase", true, "Refuse to harvest inside a player base, using the game's own player-base area - the one that stops monsters spawning there. This covers what the build-system check cannot: a grown crop is SPAWNED by the plant rather than placed, so it carries no piece and would otherwise be treated as wild. Wood is deliberately exempt - trees and logs can always be harvested, because a tree inside a base is a crop and replanting and felling is the point of a tree farm.");
			HarvestStructures = ((BaseUnityPlugin)this).Config.Bind<bool>("Harvest", "Structures", true, "Allow mining world-generated structures - marble and stone ruins, and the like. Anything a PLAYER placed is refused unconditionally and is not affected by this setting: that check uses the game's own Piece.IsPlacedByPlayer(), so your base and other players' builds are never targetable regardless.");
			HarvestAreaRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Harvest", "AreaRadius", 35f, new ConfigDescription("How far an AREA order reaches, measured from the target you pointed at and fixed there. Larger than ContinueRadius because the crew now covers it in parallel rather than one target at a time. Anchoring is what makes an area order END: searching around whoever finished last let the patch walk with them.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 100f), Array.Empty<object>()));
			HarvestAreasPerWorker = ((BaseUnityPlugin)this).Config.Bind<int>("Harvest", "AreasPerWorker", 3, new ConfigDescription("How many intact chunks of an ore node one summon is worth. A big node has room for the whole crew and they should gang up on it; a bush has room for one, and a second summon there is one not clearing the rest of the patch. Scales with the areas LEFT, so a nearly-finished node releases the crew to spread out again.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()));
			HarvestReachVertical = ((BaseUnityPlugin)this).Config.Bind<float>("Harvest", "ReachVertical", 5f, new ConfigDescription("How far ABOVE or below itself a summon can work. Kept separate from Reach, which is horizontal: a single 3D radius cannot touch the chunks left on top of a tall ore node, so the crew clears almost all of it and then swings at nothing.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 15f), Array.Empty<object>()));
			HarvestStallSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Harvest", "StallSeconds", 12f, new ConfigDescription("Give up on an ore node after this long with no area destroyed. Some geometry is simply unreachable, and standing at it forever blocks the rest of an area order. Applies only to ore and rock, where progress is measurable - never to trees, where slow is not the same as stuck.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 60f), Array.Empty<object>()));
			HarvestSwingSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Harvest", "SwingSeconds", 1.2f, new ConfigDescription("Seconds between harvest swings.", (Acc