Decompiled source of FollowerDrag v0.4.0

plugins/FollowerDrag.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Lamb.UI;
using MMTools;
using Microsoft.CodeAnalysis;
using Spine;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Follower Drag")]
[assembly: AssemblyDescription("Standalone Cult of the Lamb direct follower drag prototype.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FollowerDrag")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("87a3c5bd-34f9-4f86-b2f4-792c7e1fdc53")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyVersion("0.4.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FollowerDrag
{
	[BepInPlugin("com.cotl.followerdrag", "Follower Drag", "0.5.4")]
	public sealed class FollowerDragPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.cotl.followerdrag";

		public const string PluginName = "Follower Drag";

		public const string PluginVersion = "0.5.4";

		private FollowerDragController _controller;

		private Harmony _harmony;

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			FollowerDragConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("com.cotl.followerdrag");
			_harmony.PatchAll(typeof(FollowerDragPlugin).Assembly);
			_controller = ((Component)this).gameObject.AddComponent<FollowerDragController>();
			FollowerDragController.Instance = _controller;
			Log.LogInfo((object)"Follower Drag 0.5.4 loaded.");
		}

		private void OnDestroy()
		{
			if ((Object)(object)_controller != (Object)null)
			{
				_controller.CancelCurrentDrag();
				FollowerDragController.Instance = null;
				_controller = null;
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
		}
	}
	[HarmonyPatch(typeof(Interactor), "Update")]
	internal static class InteractorUpdatePatch
	{
		private static bool Prefix(Interactor __instance)
		{
			FollowerDragController instance = FollowerDragController.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				return !instance.ShouldSuppressVanillaInteraction(__instance);
			}
			return true;
		}
	}
	internal static class FollowerDragConfig
	{
		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<int> MouseButton;

		internal static ConfigEntry<float> HitRadius;

		internal static ConfigEntry<float> GridSnapRange;

		internal static ConfigEntry<float> MarkerSize;

		internal static ConfigEntry<bool> AssignWorkOnDrop;

		internal static ConfigEntry<float> WorkSearchRadius;

		internal static ConfigEntry<bool> SkipProtectedFollowers;

		internal static ConfigEntry<bool> ShowPrompt;

		internal static ConfigEntry<string> CarryAnimation;

		internal static ConfigEntry<float> CarryBobHeight;

		internal static ConfigEntry<float> CarryBobSpeed;

		internal static ConfigEntry<bool> UseGauntletCursor;

		internal static ConfigEntry<int> CursorMaxSize;

		internal static ConfigEntry<bool> DebugLogging;

		internal static void Bind(ConfigFile config)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Expected O, but got Unknown
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Expected O, but got Unknown
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Expected O, but got Unknown
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable direct mouse follower dragging.");
			MouseButton = config.Bind<int>("Input", "MouseButton", 0, new ConfigDescription("Mouse button used to grab and drag. 0 is left, 1 is right, 2 is middle.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
			HitRadius = config.Bind<float>("Input", "HitRadius", 0.75f, new ConfigDescription("Fallback follower hit radius when the follower collider is not directly hit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1.5f), Array.Empty<object>()));
			GridSnapRange = config.Bind<float>("Placement", "GridSnapRange", 1f, new ConfigDescription("Maximum distance from the cursor to the nearest plot grid tile.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.4f, 2.5f), Array.Empty<object>()));
			MarkerSize = config.Bind<float>("Placement", "MarkerSize", 0.72f, new ConfigDescription("Size of the drag placement marker.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 1.5f), Array.Empty<object>()));
			AssignWorkOnDrop = config.Bind<bool>("Work assignment", "AssignWorkOnDrop", true, "After a successful drop, send the follower to the nearest valid tree, waste pile, farm plot, rubble node, or unfinished build site near the release point.");
			WorkSearchRadius = config.Bind<float>("Work assignment", "WorkSearchRadius", 2.5f, new ConfigDescription("Maximum distance from the release point to look for a work target.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 6f), Array.Empty<object>()));
			SkipProtectedFollowers = config.Bind<bool>("Safety", "SkipProtectedFollowers", true, "Skip followers the game marks as explicitly locked or protected. Ordinary interaction tasks can still be interrupted by a drag.");
			ShowPrompt = config.Bind<bool>("UI", "ShowPrompt", true, "Show the small drag instruction panel while a follower is held.");
			CarryAnimation = config.Bind<string>("Held follower", "CarryAnimation", "Medic/carried-run", "Follower body animation used while the Crown is holding a follower.");
			CarryBobHeight = config.Bind<float>("Held follower", "CarryBobHeight", 0.12f, new ConfigDescription("Additional vertical bob applied to the follower while held.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.4f), Array.Empty<object>()));
			CarryBobSpeed = config.Bind<float>("Held follower", "CarryBobSpeed", 5.5f, new ConfigDescription("Speed of the held follower's floating bob.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 15f), Array.Empty<object>()));
			UseGauntletCursor = config.Bind<bool>("Cursor", "UseGauntletCursor", true, "Show the game's gauntlet artwork when hovering over or holding a follower.");
			CursorMaxSize = config.Bind<int>("Cursor", "CursorMaxSize", 72, new ConfigDescription("Maximum pixel size of the gauntlet cursor artwork.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(24, 128), Array.Empty<object>()));
			DebugLogging = config.Bind<bool>("Debug", "DebugLogging", false, "Write follower drag state changes to the BepInEx log.");
		}
	}
	internal sealed class FollowerDragController : MonoBehaviour
	{
		private enum WorkKind
		{
			None,
			Tree,
			Waste,
			Farm,
			Rubble,
			BuildSite,
			BuildProject
		}

		private sealed class WorkCandidate
		{
			internal WorkKind Kind;

			internal int StructureId;

			internal Vector3 Position;

			internal float Distance;

			internal FollowerTask CreateTask()
			{
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0097: Invalid comparison between Unknown and I4
				switch (Kind)
				{
				case WorkKind.Tree:
				{
					Structures_Tree structureByID2 = StructureManager.GetStructureByID<Structures_Tree>(StructureId);
					if (structureByID2 == null || structureByID2.TreeChopped || ((StructureBrain)structureByID2).Data == null || ((StructureBrain)structureByID2).Data.IsSapling)
					{
						return null;
					}
					return (FollowerTask)(object)new PersistentChopTreesTask(StructureId);
				}
				case WorkKind.Waste:
				{
					Structures_Waste structureByID4 = StructureManager.GetStructureByID<Structures_Waste>(StructureId);
					if (structureByID4 == null || ((StructureBrain)structureByID4).Data == null || structureByID4.ProgressFinished || (int)((StructureBrain)structureByID4).Data.Type == 414)
					{
						return null;
					}
					return (FollowerTask)(object)new PersistentCleanWasteTask(StructureId);
				}
				case WorkKind.Farm:
				{
					Structures_FarmerStation structureByID6 = StructureManager.GetStructureByID<Structures_FarmerStation>(StructureId);
					if (structureByID6 == null || ((StructureBrain)structureByID6).Data == null)
					{
						return null;
					}
					return (FollowerTask)(object)new PersistentFarmTask(StructureId);
				}
				case WorkKind.Rubble:
				{
					Structures_Rubble structureByID3 = StructureManager.GetStructureByID<Structures_Rubble>(StructureId);
					if (structureByID3 == null || structureByID3.ProgressFinished || structureByID3.AvailableSlotCount <= 0)
					{
						return null;
					}
					return (FollowerTask)(object)new PersistentClearRubbleTask(StructureId);
				}
				case WorkKind.BuildSite:
				{
					Structures_BuildSite structureByID5 = StructureManager.GetStructureByID<Structures_BuildSite>(StructureId);
					if (structureByID5 == null || structureByID5.ProgressFinished || structureByID5.IsObstructed)
					{
						return null;
					}
					return (FollowerTask)(object)new PersistentBuildTask(StructureId);
				}
				case WorkKind.BuildProject:
				{
					Structures_BuildSiteProject structureByID = StructureManager.GetStructureByID<Structures_BuildSiteProject>(StructureId);
					if (structureByID == null || structureByID.ProgressFinished)
					{
						return null;
					}
					return (FollowerTask)(object)new PersistentBuildProjectTask(StructureId);
				}
				default:
					return null;
				}
			}
		}

		private sealed class PersistentChopTreesTask : FollowerTask_ChopTrees
		{
			private const float ProgressWatchdogSeconds = 1.5f;

			private const float MinimumHitInterval = 0.12f;

			private readonly int _targetTreeId;

			private bool _sharedClaimed;

			private bool _finishing;

			private bool _progressInitialized;

			private float _lastObservedProgress;

			private float _lastProgressChangeTime;

			private float _lastHitTime = -999f;

			public override bool BlockTaskChanges => true;

			internal PersistentChopTreesTask(int treeId)
				: base(treeId)
			{
				_targetTreeId = treeId;
			}

			public override void ClaimReservations()
			{
				((FollowerTask_ChopTrees)this).ClaimReservations();
				ClaimSharedTree();
			}

			public override void ReleaseReservations()
			{
				((FollowerTask_ChopTrees)this).ReleaseReservations();
				ReleaseSharedTree();
			}

			protected override void OnStart()
			{
				Structures_Tree structureByID = StructureManager.GetStructureByID<Structures_Tree>(_targetTreeId);
				if (structureByID == null || ((StructureBrain)structureByID).Data == null || structureByID.TreeChopped || ((StructureBrain)structureByID).Data.IsSapling)
				{
					FinishAssignedTree();
					return;
				}
				ClaimSharedTree();
				((StructureBrain)structureByID).ReservedForTask = true;
				ObserveTreeProgress(structureByID);
				((FollowerTask)this).ClearDestination();
				((FollowerTask)this).SetState((FollowerTaskState)3);
			}

			public override void OnDoingBegin(Follower follower)
			{
				((FollowerTask_ChopTrees)this).OnDoingBegin(follower);
				ObserveTreeProgress(GetTargetTree());
			}

			protected override void TaskTick(float deltaGameTime)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Invalid comparison between Unknown and I4
				if ((int)((FollowerTask)this).State != 4)
				{
					return;
				}
				Structures_Tree targetTree = GetTargetTree();
				if (targetTree == null || ((StructureBrain)targetTree).Data == null || targetTree.TreeChopped)
				{
					FinishAssignedTree();
					return;
				}
				if (!_progressInitialized)
				{
					ObserveTreeProgress(targetTree);
				}
				else if (!Mathf.Approximately(((StructureBrain)targetTree).Data.Progress, _lastObservedProgress))
				{
					ObserveTreeProgress(targetTree);
				}
				if (Time.unscaledTime - _lastProgressChangeTime >= 1.5f)
				{
					((FollowerTask)this).ProgressTask();
				}
			}

			public override void ProgressTask()
			{
				if (_finishing || Time.unscaledTime - _lastHitTime < 0.12f)
				{
					return;
				}
				Structures_Tree targetTree = GetTargetTree();
				if (targetTree == null || ((StructureBrain)targetTree).Data == null || targetTree.TreeChopped)
				{
					FinishAssignedTree();
					return;
				}
				_lastHitTime = Time.unscaledTime;
				float progress = ((StructureBrain)targetTree).Data.Progress;
				targetTree.TreeHit(0.075f * ((FollowerTask)this).Brain.Info.ProductivityMultiplier, true, ((FollowerTask)this).Brain.Info.ID);
				((FollowerTask)this).Brain.GetXP(0.1f);
				ObserveTreeProgress(targetTree);
				if (Mathf.Approximately(progress, ((StructureBrain)targetTree).Data.Progress))
				{
					_lastProgressChangeTime = Time.unscaledTime;
				}
				if (targetTree.TreeChopped)
				{
					FinishAssignedTree();
				}
			}

			private Structures_Tree GetTargetTree()
			{
				return StructureManager.GetStructureByID<Structures_Tree>(_targetTreeId);
			}

			private void ObserveTreeProgress(Structures_Tree tree)
			{
				if (tree != null && ((StructureBrain)tree).Data != null)
				{
					_progressInitialized = true;
					_lastObservedProgress = ((StructureBrain)tree).Data.Progress;
					_lastProgressChangeTime = Time.unscaledTime;
				}
			}

			private void FinishAssignedTree()
			{
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Invalid comparison between Unknown and I4
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Invalid comparison between Unknown and I4
				if (!_finishing)
				{
					_finishing = true;
					if ((int)((FollowerTask)this).State != 5 && (int)((FollowerTask)this).State != 6)
					{
						((FollowerTask)this).End();
					}
				}
			}

			private void ClaimSharedTree()
			{
				if (!_sharedClaimed)
				{
					SharedTreeClaims.TryGetValue(_targetTreeId, out var value);
					SharedTreeClaims[_targetTreeId] = value + 1;
					_sharedClaimed = true;
				}
			}

			private void ReleaseSharedTree()
			{
				if (!_sharedClaimed)
				{
					return;
				}
				if (SharedTreeClaims.TryGetValue(_targetTreeId, out var value))
				{
					value--;
					if (value <= 0)
					{
						SharedTreeClaims.Remove(_targetTreeId);
					}
					else
					{
						SharedTreeClaims[_targetTreeId] = value;
						Structures_Tree structureByID = StructureManager.GetStructureByID<Structures_Tree>(_targetTreeId);
						if (structureByID != null)
						{
							((StructureBrain)structureByID).ReservedForTask = true;
						}
					}
				}
				_sharedClaimed = false;
			}
		}

		private sealed class PersistentCleanWasteTask : FollowerTask_CleanWaste
		{
			private readonly int _targetWasteId;

			private bool _sharedClaimed;

			public override bool BlockTaskChanges => true;

			internal PersistentCleanWasteTask(int wasteId)
				: base(wasteId)
			{
				_targetWasteId = wasteId;
			}

			public override void ClaimReservations()
			{
				((FollowerTask_CleanWaste)this).ClaimReservations();
				ClaimSharedWaste();
			}

			public override void ReleaseReservations()
			{
				((FollowerTask_CleanWaste)this).ReleaseReservations();
				ReleaseSharedWaste();
			}

			public override void ProgressTask()
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Invalid comparison between Unknown and I4
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Invalid comparison between Unknown and I4
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0054: Invalid comparison between Unknown and I4
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Invalid comparison between Unknown and I4
				Structures_Waste structureByID = StructureManager.GetStructureByID<Structures_Waste>(_targetWasteId);
				if (structureByID == null || structureByID.ProgressFinished)
				{
					if ((int)((FollowerTask)this).State != 5 && (int)((FollowerTask)this).State != 6)
					{
						((FollowerTask)this).End();
					}
					return;
				}
				((FollowerTask_CleanWaste)this).ProgressTask();
				structureByID = StructureManager.GetStructureByID<Structures_Waste>(_targetWasteId);
				if ((structureByID == null || structureByID.ProgressFinished) && (int)((FollowerTask)this).State != 5 && (int)((FollowerTask)this).State != 6)
				{
					((FollowerTask)this).End();
				}
			}

			private void ClaimSharedWaste()
			{
				if (!_sharedClaimed)
				{
					SharedWasteClaims.TryGetValue(_targetWasteId, out var value);
					SharedWasteClaims[_targetWasteId] = value + 1;
					_sharedClaimed = true;
				}
			}

			private void ReleaseSharedWaste()
			{
				if (!_sharedClaimed)
				{
					return;
				}
				if (SharedWasteClaims.TryGetValue(_targetWasteId, out var value))
				{
					value--;
					if (value <= 0)
					{
						SharedWasteClaims.Remove(_targetWasteId);
					}
					else
					{
						SharedWasteClaims[_targetWasteId] = value;
						Structures_Waste structureByID = StructureManager.GetStructureByID<Structures_Waste>(_targetWasteId);
						if (structureByID != null)
						{
							((StructureBrain)structureByID).ReservedForTask = true;
						}
					}
				}
				_sharedClaimed = false;
			}
		}

		private sealed class PersistentFarmTask : FollowerTask_Farm
		{
			private readonly int _stationId;

			private bool _sharedClaimed;

			public override bool BlockTaskChanges => true;

			internal PersistentFarmTask(int stationId)
				: base(stationId)
			{
				_stationId = stationId;
			}

			public override void ClaimReservations()
			{
				((FollowerTask_Farm)this).ClaimReservations();
				ClaimSharedStation();
			}

			public override void ReleaseReservations()
			{
				((FollowerTask_Farm)this).ReleaseReservations();
				ReleaseSharedStation();
			}

			private void ClaimSharedStation()
			{
				if (!_sharedClaimed)
				{
					SharedFarmStationClaims.TryGetValue(_stationId, out var value);
					SharedFarmStationClaims[_stationId] = value + 1;
					_sharedClaimed = true;
				}
			}

			private void ReleaseSharedStation()
			{
				if (!_sharedClaimed)
				{
					return;
				}
				if (SharedFarmStationClaims.TryGetValue(_stationId, out var value))
				{
					value--;
					if (value <= 0)
					{
						SharedFarmStationClaims.Remove(_stationId);
					}
					else
					{
						SharedFarmStationClaims[_stationId] = value;
						Structures_FarmerStation structureByID = StructureManager.GetStructureByID<Structures_FarmerStation>(_stationId);
						if (structureByID != null)
						{
							((StructureBrain)structureByID).ReservedForTask = true;
						}
					}
				}
				_sharedClaimed = false;
			}
		}

		private sealed class PersistentClearRubbleTask : FollowerTask_ClearRubble
		{
			public override bool BlockTaskChanges => true;

			internal PersistentClearRubbleTask(int rubbleId)
				: base(rubbleId)
			{
			}
		}

		private sealed class PersistentBuildTask : FollowerTask_Build
		{
			public override bool BlockTaskChanges => true;

			internal PersistentBuildTask(int buildSiteId)
				: base(buildSiteId)
			{
			}
		}

		private sealed class PersistentBuildProjectTask : FollowerTask_BuildProject
		{
			public override bool BlockTaskChanges => true;

			internal PersistentBuildProjectTask(int buildProjectId)
				: base(buildProjectId)
			{
			}
		}

		private enum CursorVisual
		{
			Default,
			Hover,
			Held
		}

		internal static FollowerDragController Instance;

		private Follower _draggedFollower;

		private Vector3 _originalPosition;

		private Vector3 _lastValidPosition;

		private TileGridTile _targetTile;

		private bool _targetIsValid;

		private LineRenderer _targetMarker;

		private Material _markerMaterial;

		private Texture2D _panelTexture;

		private GUIStyle _panelStyle;

		private GUIStyle _labelStyle;

		private Vector3 _grabOffset;

		private Transform _floatingSpineTransform;

		private Vector3 _originalSpineLocalPosition;

		private Quaternion _originalSpineLocalRotation;

		private Vector3 _originalSpineLocalScale;

		private string _heldBodyAnimation;

		private float _heldAnimationStartedAt;

		private float _nextHeldAnimationCheck;

		private bool _heldIconsHidden;

		private CursorVisual _cursorVisual;

		private Texture2D _openCursorTexture;

		private Texture2D _heldCursorTexture;

		private Sprite _openCursorSource;

		private Sprite _heldCursorSource;

		private float _nextCursorAssetAttempt;

		private Vector3 _lastCursorWorld;

		private static readonly Dictionary<int, int> SharedTreeClaims = new Dictionary<int, int>();

		private static readonly Dictionary<int, int> SharedWasteClaims = new Dictionary<int, int>();

		private static readonly Dictionary<int, int> SharedFarmStationClaims = new Dictionary<int, int>();

		internal void CancelCurrentDrag()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_draggedFollower != (Object)null)
			{
				EndDrag(_draggedFollower, _originalPosition, placed: false, null);
			}
			else
			{
				DestroyVisuals();
			}
			SetCursorVisual(CursorVisual.Default);
		}

		private void Update()
		{
			if ((Object)(object)_draggedFollower != (Object)null)
			{
				if (!CanUseDragInput() || Input.GetKeyDown((KeyCode)27))
				{
					CancelCurrentDrag();
				}
				else if (!Input.GetMouseButton(Mathf.Clamp(FollowerDragConfig.MouseButton.Value, 0, 2)))
				{
					FinishDrag();
				}
				else
				{
					UpdateDragTarget();
				}
			}
			else if (!CanUseDragInput())
			{
				SetCursorVisual(CursorVisual.Default);
			}
			else
			{
				UpdateHoverCursor();
				if (Input.GetMouseButtonDown(Mathf.Clamp(FollowerDragConfig.MouseButton.Value, 0, 2)))
				{
					TryBeginDrag();
				}
			}
		}

		private void LateUpdate()
		{
			if (_cursorVisual != CursorVisual.Default)
			{
				ApplyCursorVisual();
			}
		}

		private void UpdateHoverCursor()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetCursorWorld(out var world))
			{
				SetCursorVisual(CursorVisual.Default);
				return;
			}
			Follower val = FindFollowerUnderCursor(world, useFallback: false);
			SetCursorVisual(((Object)(object)val != (Object)null) ? CursorVisual.Hover : CursorVisual.Default);
		}

		private void BeginFloatingVisual(Follower follower)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			_floatingSpineTransform = null;
			_originalSpineLocalPosition = Vector3.zero;
			_originalSpineLocalRotation = Quaternion.identity;
			_originalSpineLocalScale = Vector3.one;
			_heldBodyAnimation = null;
			_heldAnimationStartedAt = Time.unscaledTime;
			_nextHeldAnimationCheck = 0f;
			_heldIconsHidden = false;
			if ((Object)(object)follower == (Object)null || (Object)(object)follower.Spine == (Object)null)
			{
				return;
			}
			_floatingSpineTransform = ((Component)follower.Spine).transform;
			_originalSpineLocalPosition = _floatingSpineTransform.localPosition;
			_originalSpineLocalRotation = _floatingSpineTransform.localRotation;
			_originalSpineLocalScale = _floatingSpineTransform.localScale;
			try
			{
				string text = FollowerDragConfig.CarryAnimation.Value;
				if (string.IsNullOrEmpty(text))
				{
					text = "Medic/carried-run";
				}
				follower.State.CURRENT_STATE = (State)49;
				follower.HideAllFollowerIcons();
				_heldIconsHidden = true;
				_heldBodyAnimation = text;
				if (text == "Medic/carried-run")
				{
					SetDirectBodyAnimation(follower, "Medic/carried-start", loop: false);
					AddDirectBodyAnimation(follower, "Medic/carried-run", loop: true, 0f);
				}
				else if (!string.IsNullOrEmpty(text))
				{
					SetDirectBodyAnimation(follower, text, loop: true);
				}
			}
			catch (Exception ex)
			{
				DebugLog("The carry animation could not be applied: " + ex.Message);
				ApplyPossessedFallback(follower);
			}
		}

		private void UpdateFloatingVisual()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_floatingSpineTransform == (Object)null) && !((Object)(object)_draggedFollower == (Object)null))
			{
				MaintainHeldAnimation(_draggedFollower);
				Vector3 originalSpineLocalPosition = _originalSpineLocalPosition;
				float value = FollowerDragConfig.CarryBobHeight.Value;
				float value2 = FollowerDragConfig.CarryBobSpeed.Value;
				originalSpineLocalPosition.y += value + Mathf.Sin(Time.unscaledTime * value2) * value * 0.35f;
				_floatingSpineTransform.localPosition = originalSpineLocalPosition;
				float num = Mathf.Sin(Time.unscaledTime * value2 * 0.72f) * 9f;
				_floatingSpineTransform.localRotation = _originalSpineLocalRotation * Quaternion.Euler(0f, 0f, num);
				_floatingSpineTransform.localScale = Vector3.Scale(_originalSpineLocalScale, new Vector3(1.03f, 0.94f, 1f));
			}
		}

		private void MaintainHeldAnimation(Follower follower)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			if ((Object)(object)follower == (Object)null || (Object)(object)follower.Spine == (Object)null || follower.Spine.AnimationState == null)
			{
				return;
			}
			try
			{
				if ((int)follower.State.CURRENT_STATE != 49)
				{
					follower.State.CURRENT_STATE = (State)49;
				}
				if (!(Time.unscaledTime < _nextHeldAnimationCheck))
				{
					_nextHeldAnimationCheck = Time.unscaledTime + 0.2f;
					string currentBodyAnimation = GetCurrentBodyAnimation(follower);
					if (_heldBodyAnimation == "Medic/carried-run" && Time.unscaledTime - _heldAnimationStartedAt > 0.65f && currentBodyAnimation != "Medic/carried-run")
					{
						DebugLog("Native carry track was replaced; using the direct possessed animation fallback.");
						ApplyPossessedFallback(follower);
					}
					else if (_heldBodyAnimation != "Medic/carried-run" && !string.IsNullOrEmpty(_heldBodyAnimation) && currentBodyAnimation != _heldBodyAnimation)
					{
						SetDirectBodyAnimation(follower, _heldBodyAnimation, loop: true);
					}
				}
			}
			catch (Exception ex)
			{
				DebugLog("Held animation maintenance failed: " + ex.Message);
				ApplyPossessedFallback(follower);
			}
		}

		private string GetCurrentBodyAnimation(Follower follower)
		{
			TrackEntry current = follower.Spine.AnimationState.GetCurrent(1);
			if (current == null || current.Animation == null)
			{
				return null;
			}
			return current.Animation.Name;
		}

		private void SetDirectBodyAnimation(Follower follower, string animation, bool loop)
		{
			follower.Spine.AnimationState.SetAnimation(1, animation, loop);
		}

		private void AddDirectBodyAnimation(Follower follower, string animation, bool loop, float delay)
		{
			follower.Spine.AnimationState.AddAnimation(1, animation, loop, delay);
		}

		private void ApplyPossessedFallback(Follower follower)
		{
			if (!((Object)(object)follower == (Object)null) && !((Object)(object)follower.Spine == (Object)null) && follower.Spine.AnimationState != null)
			{
				follower.State.CURRENT_STATE = (State)49;
				_heldBodyAnimation = "Sin/sin-floating";
				_nextHeldAnimationCheck = Time.unscaledTime + 0.2f;
				SetDirectBodyAnimation(follower, "Sin/sin-floating", loop: true);
			}
		}

		private void EndFloatingVisual(Follower follower)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_floatingSpineTransform != (Object)null)
			{
				_floatingSpineTransform.localPosition = _originalSpineLocalPosition;
				_floatingSpineTransform.localRotation = _originalSpineLocalRotation;
				_floatingSpineTransform.localScale = _originalSpineLocalScale;
			}
			if (_heldIconsHidden && (Object)(object)follower != (Object)null)
			{
				try
				{
					follower.ShowAllFollowerIcons(true);
				}
				catch (Exception ex)
				{
					DebugLog("Follower icons could not be restored: " + ex.Message);
				}
			}
			_floatingSpineTransform = null;
			_originalSpineLocalPosition = Vector3.zero;
			_originalSpineLocalRotation = Quaternion.identity;
			_originalSpineLocalScale = Vector3.one;
			_heldBodyAnimation = null;
			_heldAnimationStartedAt = 0f;
			_nextHeldAnimationCheck = 0f;
			_heldIconsHidden = false;
		}

		private void SetCursorVisual(CursorVisual visual)
		{
			if (visual == CursorVisual.Default || !FollowerDragConfig.UseGauntletCursor.Value)
			{
				if (_cursorVisual != CursorVisual.Default)
				{
					RestoreVanillaCursor();
				}
				_cursorVisual = CursorVisual.Default;
				return;
			}
			EnsureCursorAssets();
			if ((Object)(object)((visual == CursorVisual.Held) ? _heldCursorTexture : _openCursorTexture) == (Object)null)
			{
				_cursorVisual = CursorVisual.Default;
				return;
			}
			_cursorVisual = visual;
			ApplyCursorVisual();
		}

		private void ApplyCursorVisual()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = ((_cursorVisual == CursorVisual.Held) ? _heldCursorTexture : _openCursorTexture);
			if (!((Object)(object)val == (Object)null))
			{
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor((float)((Texture)val).width * 0.18f, (float)((Texture)val).height * 0.18f);
				Cursor.SetCursor(val, val2, (CursorMode)0);
			}
		}

		private void EnsureCursorAssets()
		{
			if (!FollowerDragConfig.UseGauntletCursor.Value || Time.unscaledTime < _nextCursorAssetAttempt)
			{
				return;
			}
			_nextCursorAssetAttempt = Time.unscaledTime + 1f;
			try
			{
				WeaponData weaponData = EquipmentManager.GetWeaponData((EquipmentType)400);
				WeaponData weaponData2 = EquipmentManager.GetWeaponData((EquipmentType)407);
				Sprite val = (((Object)(object)weaponData != (Object)null) ? ((EquipmentData)weaponData).UISprite : null);
				if ((Object)(object)val == (Object)null && (Object)(object)weaponData2 != (Object)null)
				{
					val = ((EquipmentData)weaponData2).UISprite;
				}
				Sprite val2 = (((Object)(object)weaponData != (Object)null) ? ((EquipmentData)weaponData).WorldSprite : null);
				if ((Object)(object)val2 == (Object)null && (Object)(object)weaponData2 != (Object)null)
				{
					val2 = (((Object)(object)((EquipmentData)weaponData2).WorldSprite != (Object)null) ? ((EquipmentData)weaponData2).WorldSprite : ((EquipmentData)weaponData2).UISprite);
				}
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = val;
				}
				if ((Object)(object)val != (Object)(object)_openCursorSource)
				{
					DestroyCursorTexture(ref _openCursorTexture);
					_openCursorSource = val;
					_openCursorTexture = CreateCursorTexture(val);
				}
				if ((Object)(object)val2 != (Object)(object)_heldCursorSource)
				{
					DestroyCursorTexture(ref _heldCursorTexture);
					_heldCursorSource = val2;
					_heldCursorTexture = CreateCursorTexture(val2);
				}
			}
			catch (Exception ex)
			{
				DebugLog("Gauntlet cursor artwork is not ready: " + ex.Message);
			}
		}

		private Texture2D CreateCursorTexture(Sprite source)
		{
			//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_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null || (Object)(object)source.texture == (Object)null)
			{
				return null;
			}
			Rect textureRect = source.textureRect;
			int num = Mathf.Clamp(Mathf.RoundToInt(((Rect)(ref textureRect)).x), 0, ((Texture)source.texture).width - 1);
			int num2 = Mathf.Clamp(Mathf.RoundToInt(((Rect)(ref textureRect)).y), 0, ((Texture)source.texture).height - 1);
			int num3 = Mathf.Clamp(Mathf.RoundToInt(((Rect)(ref textureRect)).width), 1, ((Texture)source.texture).width - num);
			int num4 = Mathf.Clamp(Mathf.RoundToInt(((Rect)(ref textureRect)).height), 1, ((Texture)source.texture).height - num2);
			RenderTexture val = new RenderTexture(((Texture)source.texture).width, ((Texture)source.texture).height, 0, (RenderTextureFormat)0);
			((Texture)val).filterMode = (FilterMode)1;
			RenderTexture active = RenderTexture.active;
			Texture2D val2 = null;
			try
			{
				Graphics.Blit((Texture)(object)source.texture, val);
				RenderTexture.active = val;
				val2 = new Texture2D(num3, num4, (TextureFormat)4, false, false);
				val2.ReadPixels(new Rect((float)num, (float)num2, (float)num3, (float)num4), 0, 0, false);
				val2.Apply(false, false);
			}
			finally
			{
				RenderTexture.active = active;
				val.Release();
				Object.Destroy((Object)(object)val);
			}
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			((Texture)val2).filterMode = (FilterMode)1;
			((Texture)val2).wrapMode = (TextureWrapMode)1;
			return ResizeCursorTexture(val2);
		}

		private Texture2D ResizeCursorTexture(Texture2D source)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Clamp(FollowerDragConfig.CursorMaxSize.Value, 24, 128);
			if (((Texture)source).width <= num && ((Texture)source).height <= num)
			{
				return source;
			}
			float num2 = Mathf.Min((float)num / (float)((Texture)source).width, (float)num / (float)((Texture)source).height);
			int num3 = Mathf.Max(1, Mathf.RoundToInt((float)((Texture)source).width * num2));
			int num4 = Mathf.Max(1, Mathf.RoundToInt((float)((Texture)source).height * num2));
			RenderTexture val = new RenderTexture(num3, num4, 0, (RenderTextureFormat)0);
			((Texture)val).filterMode = (FilterMode)1;
			RenderTexture active = RenderTexture.active;
			Texture2D val2 = null;
			try
			{
				Graphics.Blit((Texture)(object)source, val);
				RenderTexture.active = val;
				val2 = new Texture2D(num3, num4, (TextureFormat)4, false, false);
				val2.ReadPixels(new Rect(0f, 0f, (float)num3, (float)num4), 0, 0, false);
				val2.Apply(false, false);
			}
			finally
			{
				RenderTexture.active = active;
				val.Release();
				Object.Destroy((Object)(object)val);
			}
			if ((Object)(object)val2 != (Object)null)
			{
				((Texture)val2).filterMode = (FilterMode)1;
				((Texture)val2).wrapMode = (TextureWrapMode)1;
				Object.Destroy((Object)(object)source);
				return val2;
			}
			return source;
		}

		private void DestroyCursorTexture(ref Texture2D texture)
		{
			if ((Object)(object)texture != (Object)null)
			{
				Object.Destroy((Object)(object)texture);
				texture = null;
			}
		}

		private void DestroyCursorAssets()
		{
			DestroyCursorTexture(ref _openCursorTexture);
			DestroyCursorTexture(ref _heldCursorTexture);
			_openCursorSource = null;
			_heldCursorSource = null;
		}

		private void RestoreVanillaCursor()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				UIManager instance = MonoSingleton<UIManager>.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					int currentCursor = instance.currentCursor;
					int currentCursor2 = ((currentCursor == 0) ? 1 : 0);
					instance.SetCurrentCursor(currentCursor2);
					instance.SetCurrentCursor(currentCursor);
					return;
				}
			}
			catch (Exception ex)
			{
				DebugLog("The vanilla cursor could not be refreshed: " + ex.Message);
			}
			Cursor.SetCursor((Texture2D)null, Vector2.zero, (CursorMode)0);
		}

		private bool CanUseDragInput()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			if (!FollowerDragConfig.Enabled.Value || (Object)(object)PlayerFarming.Instance == (Object)null)
			{
				return false;
			}
			if ((int)PlayerFarming.Location != 1 || Time.timeScale <= 0f || SimulationManager.IsPaused)
			{
				return false;
			}
			if (LetterBox.IsPlaying || MMConversation.isPlaying || (Object)(object)PlacementObject.Instance != (Object)null)
			{
				return false;
			}
			return true;
		}

		private void TryBeginDrag()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetCursorWorld(out var world))
			{
				return;
			}
			Follower val = FindFollowerUnderCursor(world, useFallback: true);
			if ((Object)(object)val == (Object)null || !IsSelectable(val))
			{
				return;
			}
			PlacementRegion instance = PlacementRegion.Instance;
			if ((Object)(object)instance == (Object)null || instance.Grid == null || instance.Grid.Count == 0)
			{
				DebugLog("Follower drag ignored because the base plot grid is unavailable.");
				return;
			}
			_draggedFollower = val;
			_originalPosition = ((Component)val).transform.position;
			_lastValidPosition = _originalPosition;
			_grabOffset = _originalPosition - world;
			_grabOffset.z = 0f;
			_targetTile = null;
			_targetIsValid = false;
			_lastCursorWorld = world;
			try
			{
				ClearPrimaryVanillaInteraction();
				val.PickUp();
				val.ClearPath();
				val.Brain.LastPosition = ((Component)val).transform.position;
				BeginFloatingVisual(val);
				CreateVisuals();
				SetCursorVisual(CursorVisual.Held);
				UpdateDragTarget();
				DebugLog("Grabbed follower " + val.Brain.Info.ID + ".");
			}
			catch (Exception ex)
			{
				FollowerDragPlugin.Log.LogError((object)("Follower drag could not start: " + ex));
				EndDrag(val, _originalPosition, placed: false, null);
			}
		}

		internal bool ShouldSuppressVanillaInteraction(Interactor interactor)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)interactor == (Object)null || (Object)(object)PlayerFarming.Instance == (Object)null || (Object)(object)interactor != (Object)(object)PlayerFarming.Instance.interactor)
			{
				return false;
			}
			if ((Object)(object)_draggedFollower != (Object)null)
			{
				return true;
			}
			if (!CanUseDragInput())
			{
				return false;
			}
			if (!Input.GetMouseButtonDown(Mathf.Clamp(FollowerDragConfig.MouseButton.Value, 0, 2)))
			{
				return false;
			}
			if (!TryGetCursorWorld(out var world))
			{
				return false;
			}
			Follower val = FindFollowerUnderCursor(world, useFallback: true);
			if ((Object)(object)val != (Object)null)
			{
				return IsSelectable(val);
			}
			return false;
		}

		private void ClearPrimaryVanillaInteraction()
		{
			PlayerFarming instance = PlayerFarming.Instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.interactor == (Object)null))
			{
				Interactor interactor = instance.interactor;
				Interaction currentInteraction = interactor.CurrentInteraction;
				Interaction previousInteraction = interactor.PreviousInteraction;
				if ((Object)(object)currentInteraction != (Object)null)
				{
					currentInteraction.OnBecomeNotCurrent(instance);
				}
				if ((Object)(object)previousInteraction != (Object)null && (Object)(object)previousInteraction != (Object)(object)currentInteraction)
				{
					previousInteraction.OnBecomeNotCurrent(instance);
				}
				interactor.CurrentInteraction = null;
				interactor.PreviousInteraction = null;
				interactor.TempInteraction = null;
				if ((Object)(object)interactor.indicator != (Object)null)
				{
					interactor.HideIndicator();
				}
			}
		}

		private Follower FindFollowerUnderCursor(Vector3 cursorWorld, bool useFallback)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			Follower val = null;
			float num = float.MaxValue;
			Follower val2 = null;
			float num2 = float.MaxValue;
			Collider2D[] array = Physics2D.OverlapPointAll(Vector2.op_Implicit(cursorWorld));
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] == (Object)null)
				{
					continue;
				}
				Follower componentInParent = ((Component)array[i]).GetComponentInParent<Follower>();
				if (!((Object)(object)componentInParent == (Object)null) && IsInBase(componentInParent))
				{
					if (TryGetFollowerVisualHit(componentInParent, cursorWorld, out var distance) && distance < num)
					{
						val = componentInParent;
						num = distance;
					}
					float num3 = Vector2.Distance(Vector2.op_Implicit(cursorWorld), Vector2.op_Implicit(((Component)componentInParent).transform.position));
					if (num3 < num2)
					{
						val2 = componentInParent;
						num2 = num3;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if (Follower.Followers == null)
			{
				if (!((Object)(object)val2 != (Object)null) || HasFollowerVisual(val2))
				{
					return null;
				}
				return val2;
			}
			for (int j = 0; j < Follower.Followers.Count; j++)
			{
				Follower val3 = Follower.Followers[j];
				if (!((Object)(object)val3 == (Object)null) && IsInBase(val3) && TryGetFollowerVisualHit(val3, cursorWorld, out var distance2) && distance2 < num)
				{
					val = val3;
					num = distance2;
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if ((Object)(object)val2 != (Object)null && !HasFollowerVisual(val2))
			{
				return val2;
			}
			if (!useFallback)
			{
				return null;
			}
			float value = FollowerDragConfig.HitRadius.Value;
			Follower result = null;
			float num4 = float.MaxValue;
			for (int k = 0; k < Follower.Followers.Count; k++)
			{
				Follower val4 = Follower.Followers[k];
				if (!((Object)(object)val4 == (Object)null) && IsInBase(val4) && !HasFollowerVisual(val4))
				{
					float num5 = Vector2.Distance(Vector2.op_Implicit(cursorWorld), Vector2.op_Implicit(((Component)val4).transform.position));
					if (num5 <= value && num5 < num4)
					{
						result = val4;
						num4 = num5;
					}
				}
			}
			return result;
		}

		private bool TryGetFollowerVisualHit(Follower follower, Vector3 cursorWorld, out float distance)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			distance = float.MaxValue;
			if (!TryGetFollowerVisualBounds(follower, out var bounds))
			{
				return false;
			}
			if (cursorWorld.x < ((Bounds)(ref bounds)).min.x - 0.12f || cursorWorld.x > ((Bounds)(ref bounds)).max.x + 0.12f || cursorWorld.y < ((Bounds)(ref bounds)).min.y - 0.12f || cursorWorld.y > ((Bounds)(ref bounds)).max.y + 0.12f)
			{
				return false;
			}
			distance = Vector2.Distance(Vector2.op_Implicit(cursorWorld), new Vector2(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).center.y));
			return true;
		}

		private bool HasFollowerVisual(Follower follower)
		{
			Bounds bounds;
			return TryGetFollowerVisualBounds(follower, out bounds);
		}

		private bool TryGetFollowerVisualBounds(Follower follower, out Bounds bounds)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			if ((Object)(object)follower == (Object)null || (Object)(object)follower.Spine == (Object)null)
			{
				return false;
			}
			Renderer val = ((Component)follower.Spine).GetComponent<Renderer>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)follower.Spine).GetComponentInChildren<Renderer>(true);
			}
			if (!((Object)(object)val == (Object)null) && val.enabled)
			{
				Bounds bounds2 = val.bounds;
				Vector3 size = ((Bounds)(ref bounds2)).size;
				if (!(((Vector3)(ref size)).sqrMagnitude <= 0.0001f))
				{
					bounds = val.bounds;
					return true;
				}
			}
			return false;
		}

		private bool IsInBase(Follower follower)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			if ((Object)(object)follower != (Object)null && ((Behaviour)follower).isActiveAndEnabled && follower.Brain != null)
			{
				return (int)follower.Brain.Location == 1;
			}
			return false;
		}

		private bool IsSelectable(Follower follower)
		{
			if (!IsInBase(follower) || follower.Brain.Info == null)
			{
				return false;
			}
			if (!FollowerDragConfig.SkipProtectedFollowers.Value)
			{
				return true;
			}
			try
			{
				int iD = follower.Brain.Info.ID;
				bool flag = true;
				bool flag2 = true;
				bool flag3 = true;
				bool flag4 = true;
				bool flag5 = true;
				if (FollowerManager.FollowerLocked(ref iD, ref flag, ref flag2, ref flag3, ref flag4, ref flag5))
				{
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				DebugLog("Follower was skipped because its safety state could not be read: " + ex.Message);
				return false;
			}
		}

		private void UpdateDragTarget()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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)
			if ((Object)(object)_draggedFollower == (Object)null)
			{
				return;
			}
			if (!TryGetCursorWorld(out var world))
			{
				_targetTile = null;
				_targetIsValid = false;
				UpdateMarker(((Component)_draggedFollower).transform.position, valid: false);
				return;
			}
			_lastCursorWorld = world;
			PlacementRegion instance = PlacementRegion.Instance;
			TileGridTile val = null;
			if ((Object)(object)instance != (Object)null && instance.Grid != null && instance.Grid.Count > 0)
			{
				val = instance.GetClosestTileGridTileAtWorldPosition(world);
			}
			_targetTile = val;
			_targetIsValid = val != null && Vector3.Distance(val.WorldPosition, world) <= FollowerDragConfig.GridSnapRange.Value && !val.Occupied && !val.Obstructed && !val.ReservedForWaste;
			Vector3 draggedPosition = world + _grabOffset;
			draggedPosition.z = _originalPosition.z;
			SetDraggedPosition(draggedPosition);
			Vector3 center = val?.WorldPosition ?? world;
			center.z = _originalPosition.z;
			UpdateMarker(center, _targetIsValid);
			if (_targetIsValid)
			{
				Vector3 worldPosition = val.WorldPosition;
				worldPosition.z = _originalPosition.z;
				_lastValidPosition = worldPosition;
			}
			UpdateFloatingVisual();
		}

		private void SetDraggedPosition(Vector3 position)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_draggedFollower == (Object)null) && !(Vector3.SqrMagnitude(((Component)_draggedFollower).transform.position - position) < 0.0001f))
			{
				((Component)_draggedFollower).transform.position = position;
				if (_draggedFollower.Brain != null)
				{
					_draggedFollower.Brain.LastPosition = position;
				}
			}
		}

		private void FinishDrag()
		{
			//IL_0027: 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_002c: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_draggedFollower == (Object)null))
			{
				Follower draggedFollower = _draggedFollower;
				Vector3 val = (_targetIsValid ? _lastValidPosition : _originalPosition);
				WorkCandidate workCandidate = (FollowerDragConfig.AssignWorkOnDrop.Value ? FindNearestWorkCandidate(_targetIsValid ? val : _lastCursorWorld) : null);
				EndDrag(draggedFollower, val, _targetIsValid || workCandidate != null, workCandidate);
			}
		}

		private void EndDrag(Follower follower, Vector3 finalPosition, bool placed, WorkCandidate workCandidate)
		{
			//IL_0034: 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)
			_draggedFollower = null;
			_targetTile = null;
			_targetIsValid = false;
			if ((Object)(object)follower != (Object)null)
			{
				try
				{
					EndFloatingVisual(follower);
					follower.ClearPath();
					((Component)follower).transform.position = finalPosition;
					if (follower.Brain != null)
					{
						follower.Brain.LastPosition = finalPosition;
					}
					follower.Drop();
					((MonoBehaviour)this).StartCoroutine(RestoreFollowerAfterDrop(follower, follower.Brain, workCandidate));
					DebugLog((placed ? "Placed " : "Cancelled ") + "follower drag for " + follower.Brain.Info.ID + ".");
				}
				catch (Exception ex)
				{
					FollowerDragPlugin.Log.LogError((object)("Follower drag could not finish cleanly: " + ex));
					try
					{
						follower.Brain.CompleteCurrentTask();
						follower.State.CURRENT_STATE = (State)0;
					}
					catch
					{
					}
				}
			}
			DestroyVisuals();
			SetCursorVisual(CursorVisual.Default);
		}

		private IEnumerator RestoreFollowerAfterDrop(Follower follower, FollowerBrain brain, WorkCandidate workCandidate)
		{
			yield return (object)new WaitForSecondsRealtime(0.4f);
			if ((Object)(object)follower != (Object)null)
			{
				try
				{
					follower.ResetStateAnimations();
				}
				catch (Exception ex)
				{
					DebugLog("Follower animation reset failed after drag: " + ex.Message);
				}
			}
			if (brain != null && workCandidate != null && brain.CanWork)
			{
				try
				{
					FollowerTask val = workCandidate.CreateTask();
					if (val != null)
					{
						brain.HardSwapToTask(val);
						DebugLog("Assigned follower " + brain.Info.ID + " to " + workCandidate.Kind.ToString() + " " + workCandidate.StructureId + ".");
						yield break;
					}
				}
				catch (Exception ex2)
				{
					DebugLog("Work assignment failed; returning follower to vanilla task selection: " + ex2.Message);
				}
			}
			if (brain != null && (int)brain.CurrentTaskType == 0)
			{
				brain.CheckChangeTask();
			}
		}

		private WorkCandidate FindNearestWorkCandidate(Vector3 position)
		{
			//IL_0010: 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_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Invalid comparison between Unknown and I4
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0362: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Invalid comparison between Unknown and I4
			float value = FollowerDragConfig.WorkSearchRadius.Value;
			float radiusSquared = value * value;
			WorkCandidate best = null;
			FollowerLocation val = (FollowerLocation)1;
			List<Structures_Tree> allStructuresOfType = StructureManager.GetAllStructuresOfType<Structures_Tree>(ref val);
			if (allStructuresOfType != null)
			{
				for (int i = 0; i < allStructuresOfType.Count; i++)
				{
					Structures_Tree val2 = allStructuresOfType[i];
					if (val2 != null && ((StructureBrain)val2).Data != null && !val2.TreeChopped && !((StructureBrain)val2).Data.IsSapling)
					{
						ConsiderWorkCandidate(ref best, WorkKind.Tree, ((StructureBrain)val2).Data.ID, ((StructureBrain)val2).Data.Position, position, radiusSquared);
					}
				}
			}
			val = (FollowerLocation)1;
			List<Structures_Waste> allStructuresOfType2 = StructureManager.GetAllStructuresOfType<Structures_Waste>(ref val);
			if (allStructuresOfType2 != null)
			{
				for (int j = 0; j < allStructuresOfType2.Count; j++)
				{
					Structures_Waste val3 = allStructuresOfType2[j];
					if (val3 != null && ((StructureBrain)val3).Data != null && !val3.ProgressFinished && (int)((StructureBrain)val3).Data.Type != 414)
					{
						ConsiderWorkCandidate(ref best, WorkKind.Waste, ((StructureBrain)val3).Data.ID, ((StructureBrain)val3).Data.Position, position, radiusSquared);
					}
				}
			}
			val = (FollowerLocation)1;
			List<Structures_FarmerPlot> allStructuresOfType3 = StructureManager.GetAllStructuresOfType<Structures_FarmerPlot>(ref val);
			val = (FollowerLocation)1;
			List<Structures_FarmerStation> allStructuresOfType4 = StructureManager.GetAllStructuresOfType<Structures_FarmerStation>(ref val);
			if (allStructuresOfType3 != null && allStructuresOfType4 != null)
			{
				for (int k = 0; k < allStructuresOfType3.Count; k++)
				{
					Structures_FarmerPlot val4 = allStructuresOfType3[k];
					if (val4 == null || ((StructureBrain)val4).Data == null || !HasActionableFarmWork(val4))
					{
						continue;
					}
					bool flag = val4.CanPlantSeed() || val4.CanWater() || val4.CanFertilize();
					Structures_FarmerStation val5 = null;
					float num = 6.25f;
					for (int l = 0; l < allStructuresOfType4.Count; l++)
					{
						Structures_FarmerStation val6 = allStructuresOfType4[l];
						if (val6 != null && ((StructureBrain)val6).Data != null)
						{
							float num2 = Vector3.Distance(((StructureBrain)val6).Data.Position, ((StructureBrain)val4).Data.Position);
							if (num2 <= num)
							{
								val5 = val6;
								num = num2;
							}
						}
					}
					if (val5 != null && (flag || (int)((StructureBrain)val5).Data.Type == 266))
					{
						ConsiderWorkCandidate(ref best, WorkKind.Farm, ((StructureBrain)val5).Data.ID, ((StructureBrain)val4).Data.Position, position, radiusSquared);
					}
				}
			}
			val = (FollowerLocation)1;
			List<Structures_Rubble> allStructuresOfType5 = StructureManager.GetAllStructuresOfType<Structures_Rubble>(ref val);
			if (allStructuresOfType5 != null)
			{
				for (int m = 0; m < allStructuresOfType5.Count; m++)
				{
					Structures_Rubble val7 = allStructuresOfType5[m];
					if (val7 != null && ((StructureBrain)val7).Data != null && !val7.ProgressFinished && val7.AvailableSlotCount > 0)
					{
						ConsiderWorkCandidate(ref best, WorkKind.Rubble, ((StructureBrain)val7).Data.ID, ((StructureBrain)val7).Data.Position, position, radiusSquared);
					}
				}
			}
			val = (FollowerLocation)1;
			List<Structures_BuildSite> allStructuresOfType6 = StructureManager.GetAllStructuresOfType<Structures_BuildSite>(ref val);
			if (allStructuresOfType6 != null)
			{
				for (int n = 0; n < allStructuresOfType6.Count; n++)
				{
					Structures_BuildSite val8 = allStructuresOfType6[n];
					if (val8 != null && ((StructureBrain)val8).Data != null && !val8.ProgressFinished && !val8.IsObstructed)
					{
						ConsiderWorkCandidate(ref best, WorkKind.BuildSite, ((StructureBrain)val8).Data.ID, ((StructureBrain)val8).Data.Position, position, radiusSquared);
					}
				}
			}
			val = (FollowerLocation)1;
			List<Structures_BuildSiteProject> allStructuresOfType7 = StructureManager.GetAllStructuresOfType<Structures_BuildSiteProject>(ref val);
			if (allStructuresOfType7 != null)
			{
				for (int num3 = 0; num3 < allStructuresOfType7.Count; num3++)
				{
					Structures_BuildSiteProject val9 = allStructuresOfType7[num3];
					if (val9 != null && ((StructureBrain)val9).Data != null && !val9.ProgressFinished)
					{
						ConsiderWorkCandidate(ref best, WorkKind.BuildProject, ((StructureBrain)val9).Data.ID, ((StructureBrain)val9).Data.Position, position, radiusSquared);
					}
				}
			}
			return best;
		}

		private static bool HasActionableFarmWork(Structures_FarmerPlot plot)
		{
			try
			{
				return plot.CanPlantSeed() || plot.CanWater() || plot.CanFertilize() || plot.CanPickCrop();
			}
			catch
			{
				return false;
			}
		}

		private void ConsiderWorkCandidate(ref WorkCandidate best, WorkKind kind, int structureId, Vector3 candidatePosition, Vector3 releasePosition, float radiusSquared)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = candidatePosition - releasePosition;
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			if (!(sqrMagnitude > radiusSquared) && (best == null || !(sqrMagnitude >= best.Distance * best.Distance)))
			{
				best = new WorkCandidate
				{
					Kind = kind,
					StructureId = structureId,
					Position = candidatePosition,
					Distance = Mathf.Sqrt(sqrMagnitude)
				};
			}
		}

		private bool TryGetCursorWorld(out Vector3 world)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			world = Vector3.zero;
			Camera val = (((Object)(object)CameraManager.instance != (Object)null) ? CameraManager.instance.CameraRef : Camera.main);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Plane val2 = default(Plane);
			((Plane)(ref val2))..ctor(Vector3.forward, Vector3.zero);
			Ray val3 = val.ScreenPointToRay(Input.mousePosition);
			float num = default(float);
			if (!((Plane)(ref val2)).Raycast(val3, ref num))
			{
				return false;
			}
			world = ((Ray)(ref val3)).GetPoint(num);
			world.z = 0f;
			return true;
		}

		private void CreateVisuals()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			DestroyVisuals();
			GameObject val = new GameObject("FollowerDragTarget");
			val.transform.SetParent(((Component)this).transform, false);
			_targetMarker = val.AddComponent<LineRenderer>();
			_targetMarker.useWorldSpace = true;
			_targetMarker.loop = false;
			_targetMarker.positionCount = 5;
			_targetMarker.widthMultiplier = 0.06f;
			_targetMarker.numCapVertices = 2;
			((Renderer)_targetMarker).sortingOrder = 500;
			_markerMaterial = CreateMarkerMaterial();
			if ((Object)(object)_markerMaterial != (Object)null)
			{
				((Renderer)_targetMarker).sharedMaterial = _markerMaterial;
			}
		}

		private Material CreateMarkerMaterial()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			Shader val = Shader.Find("Sprites/Default");
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			return new Material(val)
			{
				hideFlags = (HideFlags)61
			};
		}

		private void UpdateMarker(Vector3 center, bool valid)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_targetMarker == (Object)null))
			{
				float num = FollowerDragConfig.MarkerSize.Value * 0.5f;
				Vector3 val = center + new Vector3(0f, num, -0.05f);
				Vector3 val2 = center + new Vector3(num, 0f, -0.05f);
				Vector3 val3 = center + new Vector3(0f, 0f - num, -0.05f);
				Vector3 val4 = center + new Vector3(0f - num, 0f, -0.05f);
				_targetMarker.SetPosition(0, val);
				_targetMarker.SetPosition(1, val2);
				_targetMarker.SetPosition(2, val3);
				_targetMarker.SetPosition(3, val4);
				_targetMarker.SetPosition(4, val);
				Color val5 = (valid ? new Color(0.2f, 1f, 0.35f, 0.95f) : new Color(1f, 0.2f, 0.2f, 0.95f));
				_targetMarker.startColor = val5;
				_targetMarker.endColor = val5;
			}
		}

		private void DestroyVisuals()
		{
			if ((Object)(object)_targetMarker != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)_targetMarker).gameObject);
				_targetMarker = null;
			}
			if ((Object)(object)_markerMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)_markerMaterial);
				_markerMaterial = null;
			}
		}

		private void OnGUI()
		{
			//IL_00b0: 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)
			if (!((Object)(object)_draggedFollower == (Object)null) && FollowerDragConfig.ShowPrompt.Value)
			{
				EnsureGuiStyles();
				float num = Mathf.Min(520f, (float)Screen.width - 32f);
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(((float)Screen.width - num) * 0.5f, (float)Screen.height - 82f, num, 58f);
				string text = ((_draggedFollower.Brain != null && _draggedFollower.Brain.Info != null) ? _draggedFollower.Brain.Info.Name : "Follower");
				string text2 = (_targetIsValid ? "Release to place" : "Move over an open plot tile");
				GUI.Box(val, GUIContent.none, _panelStyle);
				GUI.Label(new Rect(((Rect)(ref val)).x + 12f, ((Rect)(ref val)).y + 7f, ((Rect)(ref val)).width - 24f, ((Rect)(ref val)).height - 14f), "Crown drag: " + text + "\n" + text2 + "  |  Esc: cancel", _labelStyle);
			}
		}

		private void EnsureGuiStyles()
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			if (_panelStyle == null)
			{
				_panelTexture = new Texture2D(1, 1, (TextureFormat)4, false);
				((Object)_panelTexture).hideFlags = (HideFlags)61;
				_panelTexture.SetPixel(0, 0, new Color(0f, 0f, 0f, 0.82f));
				_panelTexture.Apply();
				_panelStyle = new GUIStyle(GUI.skin.box);
				_panelStyle.normal.background = _panelTexture;
				_panelStyle.border = new RectOffset(8, 8, 8, 8);
				_panelStyle.padding = new RectOffset(8, 8, 6, 6);
				_labelStyle = new GUIStyle(GUI.skin.label);
				_labelStyle.alignment = (TextAnchor)4;
				_labelStyle.fontSize = 16;
				_labelStyle.normal.textColor = Color.white;
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			CancelCurrentDrag();
			DestroyVisuals();
			RestoreVanillaCursor();
			DestroyCursorAssets();
			if ((Object)(object)_panelTexture != (Object)null)
			{
				Object.Destroy((Object)(object)_panelTexture);
				_panelTexture = null;
			}
		}

		private static void DebugLog(string message)
		{
			if (FollowerDragConfig.DebugLogging.Value && FollowerDragPlugin.Log != null)
			{
				FollowerDragPlugin.Log.LogInfo((object)("[FollowerDrag] " + message));
			}
		}
	}
}