Decompiled source of Better Tracing v1.0.1

BetterTracing.dll

Decompiled 20 hours ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using DM;
using GamepadUI.StateManager.Core;
using HarmonyLib;
using InControl;
using Landfall.TABS;
using Landfall.TABS.AI;
using Landfall.TABS.AI.Components;
using Landfall.TABS.AI.Components.Modifiers;
using Landfall.TABS.AI.Components.Pathfinding;
using Landfall.TABS.AI.Components.Tags;
using Landfall.TABS.AI.Systems;
using Landfall.TABS.GameMode;
using Landfall.TABS.GameState;
using Landfall.TABS.UnitEditor;
using Landfall.TABS.UnitPlacement;
using Landfall.TABS.WinConditions;
using Landfall.TABS.Workshop;
using Landfall.TABS_Input;
using Microsoft.CodeAnalysis;
using Pathfinding;
using TFBGames;
using TMPro;
using UIStateManager;
using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Tabs.PersistentHealth.Mod
{
	internal static class AssassinPoofCompatibility
	{
		internal static readonly DatabaseID LegacyAbilityId = new DatabaseID(-2, 1847012603);

		private static SpecialAbility s_nativeAbility;

		internal static bool PersonalOverrideEnabled => false;

		private static SpecialAbility ResolveNativeAbility(LandfallContentDatabase database = null)
		{
			if ((Object)(object)s_nativeAbility != (Object)null)
			{
				return s_nativeAbility;
			}
			if (database == null)
			{
				ContentDatabase obj = ContentDatabase.Instance();
				database = ((obj != null) ? obj.LandfallContentDatabase : null);
			}
			if (database == null)
			{
				return null;
			}
			s_nativeAbility = (from move in database.GetCombatMoves()
				where (Object)(object)move != (Object)null && (Object)(object)move.GetComponent<AssassinPoofEffect>() != (Object)null
				select move.GetComponent<SpecialAbility>() into ability
				where (Object)(object)ability != (Object)null && ((CharacterItem)ability).Entity != null && ((CharacterItem)ability).Entity.GUID.m_modID == DatabaseID._LANDFALL_CONTENT
				orderby (((CharacterItem)ability).DisplayName ?? string.Empty).IndexOf("Assassin", StringComparison.OrdinalIgnoreCase) >= 0 descending
				select ability).FirstOrDefault();
			return s_nativeAbility;
		}

		internal static bool IsNativeAssassinPoof(AssassinPoofEffect effect)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			SpecialAbility val = (((Object)(object)effect != (Object)null) ? ((Component)effect).GetComponent<SpecialAbility>() : null);
			SpecialAbility val2 = (((Object)(object)val != (Object)null) ? ResolveNativeAbility() : null);
			if (((val != null) ? ((CharacterItem)val).Entity : null) != null && ((val2 != null) ? ((CharacterItem)val2).Entity : null) != null)
			{
				return ((CharacterItem)val).Entity.GUID == ((CharacterItem)val2).Entity.GUID;
			}
			return false;
		}

		internal static bool TryAttachToSpawnedUnit(AssassinPoofEffect effect)
		{
			if (!PersonalOverrideEnabled || (Object)(object)effect == (Object)null)
			{
				return false;
			}
			Unit component = ((Component)((Component)effect).transform.root).GetComponent<Unit>();
			if ((Object)(object)component == (Object)null || !IsNativeAssassinPoof(effect))
			{
				return false;
			}
			if ((Object)(object)((Component)component).GetComponentInChildren<ModAssassinPoofEffect>(true) == (Object)null)
			{
				((Component)effect).gameObject.AddComponent<ModAssassinPoofEffect>().CopyPresentationFrom(effect);
			}
			effect.automatic = false;
			((MonoBehaviour)effect).StopAllCoroutines();
			((Behaviour)effect).enabled = false;
			return true;
		}

		internal static void MigrateLegacyAbility(SerializedUnitBlueprint data, LandfallContentDatabase database = null)
		{
			//IL_0014: 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)
			if (data?.m_combatMoves != null && data.m_combatMoves.Contains(LegacyAbilityId))
			{
				SpecialAbility val = ResolveNativeAbility(database);
				if (((val != null) ? ((CharacterItem)val).Entity : null) == null)
				{
					BetterTracingPlugin.LogPluginWarning("Could not convert the old modded Assassin Poof: the vanilla ability is unavailable.");
				}
				else
				{
					ReplaceLegacyAbilityIds(data, ((CharacterItem)val).Entity.GUID);
				}
			}
		}

		internal static void ReplaceLegacyAbilityIds(SerializedUnitBlueprint data, DatabaseID nativeId)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			if (data?.m_combatMoves != null && !((DatabaseID)(ref nativeId)).IsDefaultID() && !(nativeId == LegacyAbilityId))
			{
				data.m_combatMoves = data.m_combatMoves.Select((DatabaseID id) => (!(id == LegacyAbilityId)) ? id : nativeId).ToArray();
			}
		}
	}
	public sealed class ModAssassinPoofEffect : MonoBehaviour
	{
		private readonly struct BodyShape
		{
			internal readonly float BottomY;

			internal readonly float LowerExtent;

			internal readonly float UpperExtent;

			internal readonly float Radius;

			internal BodyShape(float bottomY, float lowerExtent, float upperExtent, float radius)
			{
				BottomY = bottomY;
				LowerExtent = lowerExtent;
				UpperExtent = upperExtent;
				Radius = radius;
			}
		}

		private readonly struct RigidbodySnapshot
		{
			internal readonly Rigidbody Rigidbody;

			internal readonly bool WasKinematic;

			internal readonly bool DetectedCollisions;

			internal RigidbodySnapshot(Rigidbody rigidbody, bool wasKinematic, bool detectedCollisions)
			{
				Rigidbody = rigidbody;
				WasKinematic = wasKinematic;
				DetectedCollisions = detectedCollisions;
			}
		}

		private const int NormalCandidateAttempts = 40;

		private const int ExpandedCandidateAttempts = 72;

		private const float GoldenAngleDegrees = 137.50777f;

		private const float MaximumGroundDrop = 10f;

		private const float MinimumWalkableNormalY = 0.55f;

		private const float LandingClearance = 0.08f;

		private const float WallClearance = 0.14f;

		private Unit m_unit;

		private CanDoUnitEvents m_canDo;

		private ParticleSystem m_particles;

		private AssassinPoofEffect m_nativePresentation;

		private UnityEvent m_poofEvent;

		private float m_counter;

		private bool m_done;

		private bool m_initialized;

		private float TriggerDelaySeconds => UnitAbilityRuntime.Number((Component)(object)m_nativePresentation, "activationDelay", 0.28f);

		private float MoveDelaySeconds => UnitAbilityRuntime.Number((Component)(object)m_nativePresentation, "moveDelay", 0.015f);

		private float BacklineFraction => UnitAbilityRuntime.Number((Component)(object)m_nativePresentation, "backlinePercent", 40f) / 100f;

		private float MinimumTargetRadius => UnitAbilityRuntime.Number((Component)(object)m_nativePresentation, "distanceFromUnit", 2f);

		private float NormalSearchWidth => UnitAbilityRuntime.Number((Component)(object)m_nativePresentation, "searchWidth", 3.5f);

		private float ExpandedSearchWidth => NormalSearchWidth + 2.5f;

		internal void CopyPresentationFrom(AssassinPoofEffect nativeEffect)
		{
			m_nativePresentation = nativeEffect;
			m_poofEvent = (((Object)(object)nativeEffect != (Object)null) ? nativeEffect.poofEvent : null);
		}

		private void Start()
		{
			//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)
			m_unit = ((Component)((Component)this).transform.root).GetComponent<Unit>();
			if ((Object)(object)m_unit == (Object)null)
			{
				return;
			}
			ModAssassinPoofEffect[] componentsInChildren = ((Component)((Component)m_unit).transform.root).GetComponentsInChildren<ModAssassinPoofEffect>(true);
			if (componentsInChildren.Length != 0 && (Object)(object)componentsInChildren[0] != (Object)(object)this)
			{
				((Behaviour)this).enabled = false;
				return;
			}
			m_canDo = ((Component)this).GetComponent<CanDoUnitEvents>();
			m_nativePresentation = ((Component)this).GetComponent<AssassinPoofEffect>();
			if ((Object)(object)m_nativePresentation != (Object)null)
			{
				m_nativePresentation.automatic = false;
				((Behaviour)m_nativePresentation).enabled = false;
				m_poofEvent = m_nativePresentation.poofEvent;
			}
			DisableNativePoofEffectsOnUnit(m_unit);
			m_particles = ((Component)this).GetComponentInChildren<ParticleSystem>();
			if ((Object)(object)m_particles != (Object)null)
			{
				try
				{
					ShapeModule shape = m_particles.shape;
					((ShapeModule)(ref shape)).skinnedMeshRenderer = ((Component)((Component)this).transform.root).GetComponentInChildren<SkinnedMeshRenderer>();
				}
				catch
				{
				}
			}
			m_counter = Random.Range(0f, 0.08f);
			m_initialized = true;
		}

		private static void DisableNativePoofEffectsOnUnit(Unit owner)
		{
			if ((Object)(object)owner == (Object)null)
			{
				return;
			}
			AssassinPoofEffect[] componentsInChildren = ((Component)((Component)owner).transform.root).GetComponentsInChildren<AssassinPoofEffect>(true);
			foreach (AssassinPoofEffect val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && AssassinPoofCompatibility.IsNativeAssassinPoof(val))
				{
					val.automatic = false;
					((MonoBehaviour)val).StopAllCoroutines();
					((Behaviour)val).enabled = false;
				}
			}
		}

		private void Update()
		{
			if (m_initialized && !m_done && !((Object)(object)m_unit == (Object)null) && !m_unit.dead && !((Object)(object)m_unit.data == (Object)null) && !m_unit.data.Dead && (!((Object)(object)m_canDo != (Object)null) || m_canDo.canDoStuff))
			{
				m_counter += Time.deltaTime;
				if (!(m_counter <= TriggerDelaySeconds))
				{
					m_done = true;
					((MonoBehaviour)this).StartCoroutine(DoSafePoof());
				}
			}
		}

		private IEnumerator DoSafePoof()
		{
			if (!TryChooseSafeTeleportDestination(out var target, out var teleportDelta, out var groundPoint, out var groundNormal))
			{
				yield break;
			}
			if ((Object)(object)m_particles != (Object)null)
			{
				m_particles.Emit(25);
			}
			yield return (object)new WaitForSeconds(MoveDelaySeconds);
			if (IsLiveUnit(m_unit) && TryChooseSafeTeleportDestination(out target, out teleportDelta, out groundPoint, out groundNormal))
			{
				List<RigidbodySnapshot> snapshots = FreezeRagdollForTeleport(m_unit);
				MoveRagdollAsOne(m_unit, teleportDelta);
				SnapFeetToGround(m_unit, groundPoint.y);
				if ((Object)(object)m_unit.data != (Object)null)
				{
					m_unit.data.TouchGround(groundPoint, groundNormal, (Rigidbody)null);
				}
				UnityEvent poofEvent = m_poofEvent;
				if (poofEvent != null)
				{
					poofEvent.Invoke();
				}
				if ((Object)(object)m_particles != (Object)null)
				{
					m_particles.Play();
				}
				yield return (object)new WaitForFixedUpdate();
				RestoreRagdollAfterTeleport(m_unit, snapshots);
			}
		}

		private bool TryChooseSafeTeleportDestination(out Unit target, out Vector3 teleportDelta, out Vector3 groundPoint, out Vector3 groundNormal)
		{
			//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_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			target = null;
			teleportDelta = Vector3.zero;
			groundPoint = Vector3.zero;
			groundNormal = Vector3.up;
			if (!IsLiveUnit(m_unit))
			{
				return false;
			}
			List<Unit> list = (from candidate in Object.FindObjectsOfType<Unit>()
				where IsLiveUnit(candidate) && (Object)(object)candidate != (Object)(object)m_unit && candidate.Team != m_unit.Team
				orderby Vector3.Distance(m_unit.data.mainRig.position, candidate.data.mainRig.position) descending
				select candidate).ToList();
			if (list.Count == 0)
			{
				return false;
			}
			int num = Mathf.Clamp(Mathf.CeilToInt((float)list.Count * BacklineFraction), 1, list.Count);
			ShuffleRange(list, 0, num);
			ShuffleRange(list, num, list.Count - num);
			foreach (Unit item in list)
			{
				if (TryFindSafeDestinationAroundTarget(m_unit, item, expandedSearch: false, out var groundedDelta, out var groundPoint2, out var groundNormal2))
				{
					target = item;
					teleportDelta = groundedDelta;
					groundPoint = groundPoint2;
					groundNormal = groundNormal2;
					return true;
				}
			}
			foreach (Unit item2 in list)
			{
				if (TryFindSafeDestinationAroundTarget(m_unit, item2, expandedSearch: true, out var groundedDelta2, out var groundPoint3, out var groundNormal3))
				{
					target = item2;
					teleportDelta = groundedDelta2;
					groundPoint = groundPoint3;
					groundNormal = groundNormal3;
					return true;
				}
			}
			return false;
		}

		private static void ShuffleRange(List<Unit> units, int start, int count)
		{
			for (int num = start + count - 1; num > start; num--)
			{
				int num2 = Random.Range(start, num + 1);
				int index = num;
				int index2 = num2;
				Unit value = units[num2];
				Unit value2 = units[num];
				units[index] = value;
				units[index2] = value2;
			}
		}

		private bool TryFindSafeDestinationAroundTarget(Unit caster, Unit target, bool expandedSearch, out Vector3 groundedDelta, out Vector3 groundPoint, out Vector3 groundNormal)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: 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_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)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: 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_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			groundedDelta = Vector3.zero;
			groundPoint = Vector3.zero;
			groundNormal = Vector3.up;
			if (!IsLiveUnit(caster) || !IsLiveUnit(target) || !TryGetBodyShape(caster, out var shape))
			{
				return false;
			}
			float num = 0.55f;
			if (TryGetBodyShape(target, out var shape2))
			{
				num = shape2.Radius;
			}
			float num2 = Mathf.Max(MinimumTargetRadius, shape.Radius + num + 0.5f);
			float num3 = (expandedSearch ? ExpandedSearchWidth : NormalSearchWidth);
			int num4 = (expandedSearch ? 72 : 40);
			float num5 = Random.Range(0f, 360f);
			for (int i = 0; i < num4; i++)
			{
				float num6 = num5 + (float)i * 137.50777f + Random.Range(-9f, 9f);
				float num7 = (float)(i % 6) / 5f;
				float num8 = num2 + num7 * num3 + Random.Range(-0.12f, 0.12f);
				Vector3 val = Quaternion.Euler(0f, num6, 0f) * Vector3.forward;
				Vector3 horizontalPoint = target.data.mainRig.position + val * num8;
				if (TryBuildSafeGroundedDestination(caster, target, shape, horizontalPoint, out groundedDelta, out groundPoint, out groundNormal))
				{
					return true;
				}
			}
			Vector3 val2 = caster.data.mainRig.position - target.data.mainRig.position;
			val2.y = 0f;
			if (((Vector3)(ref val2)).sqrMagnitude > 0.001f)
			{
				((Vector3)(ref val2)).Normalize();
				for (int j = 0; j < 4; j++)
				{
					Vector3 horizontalPoint2 = target.data.mainRig.position + val2 * (num2 + (float)j * 0.8f);
					if (TryBuildSafeGroundedDestination(caster, target, shape, horizontalPoint2, out groundedDelta, out groundPoint, out groundNormal))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryBuildSafeGroundedDestination(Unit caster, Unit target, BodyShape casterShape, Vector3 horizontalPoint, out Vector3 groundedDelta, out Vector3 groundPoint, out Vector3 groundNormal)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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)
			//IL_003b: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_0099: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			groundedDelta = Vector3.zero;
			groundPoint = Vector3.zero;
			groundNormal = Vector3.up;
			Vector3 position = caster.data.mainRig.position;
			if (!TryFindGroundBelow(new Vector3(horizontalPoint.x, Mathf.Max(position.y, target.data.mainRig.position.y) + 2f, horizontalPoint.z), out var ground))
			{
				return false;
			}
			float num = position.y - casterShape.BottomY;
			if (num < 0f)
			{
				return false;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(horizontalPoint.x, ((RaycastHit)(ref ground)).point.y + num + 0.08f, horizontalPoint.z);
			if (!IsLandingVolumeClear(val, casterShape, caster))
			{
				return false;
			}
			if (HasEnvironmentBetweenTargetAndDestination(target, val))
			{
				return false;
			}
			groundedDelta = val - position;
			if (!AreTranslatedUnitCollidersClear(caster, groundedDelta))
			{
				groundedDelta = Vector3.zero;
				return false;
			}
			groundPoint = ((RaycastHit)(ref ground)).point;
			groundNormal = ((RaycastHit)(ref ground)).normal;
			return true;
		}

		private static bool TryFindGroundBelow(Vector3 destination, out RaycastHit ground)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_0093: 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_00c0: 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)
			ground = default(RaycastHit);
			RaycastHit[] array = Physics.RaycastAll(destination + Vector3.up * 2f, Vector3.down, 12f, -1, (QueryTriggerInteraction)1);
			Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance));
			RaycastHit[] array2 = array;
			for (int num = 0; num < array2.Length; num++)
			{
				RaycastHit val = array2[num];
				Collider collider = ((RaycastHit)(ref val)).collider;
				if (!((Object)(object)collider == (Object)null) && !IsUnitCollider(collider) && !(((RaycastHit)(ref val)).normal.y < 0.55f) && !(destination.y - ((RaycastHit)(ref val)).point.y > 10f) && !(((RaycastHit)(ref val)).point.y > destination.y + 0.25f))
				{
					ground = val;
					return true;
				}
			}
			return false;
		}

		private static bool IsLandingVolumeClear(Vector3 mainRigPosition, BodyShape shape, Unit caster)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_0052: 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_00bc: 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_00df: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			float num = shape.Radius + 0.14f;
			Vector3 val = mainRigPosition + Vector3.down * Mathf.Max(0f, shape.LowerExtent - num);
			Vector3 val2 = mainRigPosition + Vector3.up * Mathf.Max(0f, shape.UpperExtent - num);
			Collider[] array = Physics.OverlapCapsule(val, val2, num, -1, (QueryTriggerInteraction)1);
			foreach (Collider val3 in array)
			{
				if (!((Object)(object)val3 == (Object)null) && !((Component)val3).transform.IsChildOf(((Component)caster).transform))
				{
					return false;
				}
			}
			float num2 = Mathf.Max(0.12f, (shape.LowerExtent + shape.UpperExtent) * 0.5f - 0.06f);
			Vector3 val4 = mainRigPosition + Vector3.up * ((shape.UpperExtent - shape.LowerExtent) * 0.5f + 0.06f);
			Vector3 val5 = default(Vector3);
			((Vector3)(ref val5))..ctor(num * 1.08f, num2, num * 1.08f);
			array = Physics.OverlapBox(val4, val5, Quaternion.identity, -1, (QueryTriggerInteraction)1);
			foreach (Collider val6 in array)
			{
				if (!((Object)(object)val6 == (Object)null) && !((Component)val6).transform.IsChildOf(((Component)caster).transform))
				{
					return false;
				}
			}
			return true;
		}

		private static bool HasEnvironmentBetweenTargetAndDestination(Unit target, Vector3 destination)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = target.data.mainRig.position + Vector3.up * 0.15f;
			Vector3 val2 = destination - val;
			float magnitude = ((Vector3)(ref val2)).magnitude;
			if (magnitude < 0.25f)
			{
				return false;
			}
			RaycastHit[] array = Physics.RaycastAll(val, val2 / magnitude, magnitude, -1, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val3 = array[i];
				if (!((Object)(object)((RaycastHit)(ref val3)).collider == (Object)null) && !IsUnitCollider(((RaycastHit)(ref val3)).collider) && ((RaycastHit)(ref val3)).distance > 0.15f && ((RaycastHit)(ref val3)).distance < magnitude - 0.1f)
				{
					return true;
				}
			}
			return false;
		}

		private static bool AreTranslatedUnitCollidersClear(Unit caster, Vector3 delta)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			Collider[] componentsInChildren = ((Component)((Component)caster).transform.root).GetComponentsInChildren<Collider>(true);
			Vector3 val3 = default(Vector3);
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || !val.enabled || val.isTrigger)
				{
					continue;
				}
				Bounds bounds = val.bounds;
				float num = Mathf.Max(((Bounds)(ref bounds)).extents.x, ((Bounds)(ref bounds)).extents.z) + 0.14f;
				Vector3 val2 = ((Bounds)(ref bounds)).center + delta + Vector3.up * 0.04f;
				((Vector3)(ref val3))..ctor(num, Mathf.Max(0.02f, ((Bounds)(ref bounds)).extents.y - 0.04f), num);
				Collider[] array = Physics.OverlapBox(val2, val3, Quaternion.identity, -1, (QueryTriggerInteraction)1);
				foreach (Collider val4 in array)
				{
					if (!((Object)(object)val4 == (Object)null) && !((Component)val4).transform.IsChildOf(((Component)caster).transform))
					{
						return false;
					}
				}
			}
			return true;
		}

		private static bool TryGetBodyShape(Unit unit, out BodyShape shape)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			shape = default(BodyShape);
			if (!IsLiveUnit(unit))
			{
				return false;
			}
			Vector3 position = unit.data.mainRig.position;
			Bounds val = default(Bounds);
			bool flag = false;
			Rigidbody[] array = (((Object)(object)unit.data.allRigs != (Object)null) ? unit.data.allRigs.AllRigs : ((Component)unit).GetComponentsInChildren<Rigidbody>());
			foreach (Rigidbody val2 in array)
			{
				if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).GetComponentInParent<Weapon>() != (Object)null)
				{
					continue;
				}
				Collider[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Collider>();
				foreach (Collider val3 in componentsInChildren)
				{
					if (!((Object)(object)val3 == (Object)null) && val3.enabled && !val3.isTrigger)
					{
						if (!flag)
						{
							val = val3.bounds;
							flag = true;
						}
						else
						{
							((Bounds)(ref val)).Encapsulate(val3.bounds);
						}
					}
				}
			}
			float num = Mathf.Clamp(((Object)(object)unit.unitBlueprint != (Object)null) ? unit.unitBlueprint.sizeMultiplier : 1f, 0.5f, 3f);
			if (!flag)
			{
				shape = new BodyShape(position.y - 0.8f * num, 0.8f * num, 0.8f * num, 0.45f * num);
				return true;
			}
			float bottomY;
			float num2 = (TryGetActualFootBottomY(unit, out bottomY) ? bottomY : ((Bounds)(ref val)).min.y);
			float lowerExtent = Mathf.Clamp(position.y - num2, 0.35f * num, 2.5f * num);
			float upperExtent = Mathf.Clamp(((Bounds)(ref val)).max.y - position.y, 0.35f * num, 2.5f * num);
			float radius = Mathf.Clamp(Mathf.Max(((Bounds)(ref val)).extents.x, ((Bounds)(ref val)).extents.z) * 0.72f, 0.38f * num, 1.15f * num);
			shape = new BodyShape(num2, lowerExtent, upperExtent, radius);
			return true;
		}

		private static bool TryGetActualFootBottomY(Unit unit, out float bottomY)
		{
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			bottomY = float.PositiveInfinity;
			if ((Object)(object)unit?.data == (Object)null)
			{
				return false;
			}
			bool flag = false;
			Transform[] array = (Transform[])(object)new Transform[2]
			{
				unit.data.footLeft,
				unit.data.footRight
			};
			Transform[] array2 = array;
			foreach (Transform val in array2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Rigidbody component = ((Component)val).GetComponent<Rigidbody>();
				Collider[] array3 = (((Object)(object)component != (Object)null) ? ((Component)component).GetComponentsInChildren<Collider>() : ((Component)val).GetComponentsInChildren<Collider>());
				foreach (Collider val2 in array3)
				{
					if (!((Object)(object)val2 == (Object)null) && val2.enabled && !val2.isTrigger && (!((Object)(object)component != (Object)null) || !((Object)(object)val2.attachedRigidbody != (Object)(object)component)))
					{
						float num = bottomY;
						Bounds bounds = val2.bounds;
						bottomY = Mathf.Min(num, ((Bounds)(ref bounds)).min.y);
						flag = true;
					}
				}
			}
			if (flag)
			{
				return true;
			}
			float num2 = Mathf.Clamp(((Object)(object)unit.unitBlueprint != (Object)null) ? unit.unitBlueprint.sizeMultiplier : 1f, 0.5f, 3f);
			array2 = array;
			foreach (Transform val3 in array2)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					bottomY = Mathf.Min(bottomY, val3.position.y - 0.12f * num2);
				}
			}
			return !float.IsPositiveInfinity(bottomY);
		}

		private static bool IsUnitCollider(Collider collider)
		{
			if ((Object)(object)collider != (Object)null)
			{
				return (Object)(object)((Component)collider).GetComponentInParent<Unit>() != (Object)null;
			}
			return false;
		}

		private static bool IsLiveUnit(Unit unit)
		{
			if ((Object)(object)unit != (Object)null && !unit.dead && (Object)(object)unit.data != (Object)null && !unit.data.Dead && (Object)(object)unit.data.mainRig != (Object)null)
			{
				return unit.data.health > 0f;
			}
			return false;
		}

		private static List<RigidbodySnapshot> FreezeRagdollForTeleport(Unit unit)
		{
			//IL_004a: 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)
			List<RigidbodySnapshot> list = new List<RigidbodySnapshot>();
			Rigidbody[] componentsInChildren = ((Component)((Component)unit).transform.root).GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					list.Add(new RigidbodySnapshot(val, val.isKinematic, val.detectCollisions));
					if (!val.isKinematic)
					{
						val.velocity = Vector3.zero;
						val.angularVelocity = Vector3.zero;
					}
					val.detectCollisions = false;
					val.isKinematic = true;
				}
			}
			return list;
		}

		private static void MoveRagdollAsOne(Unit unit, Vector3 delta)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			MoveRagdollAsOne(unit, delta, rotateBodyChildren: true);
		}

		private static void MoveRagdollAsOne(Unit unit, Vector3 delta, bool rotateBodyChildren)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: 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)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: 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_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: 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_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: 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_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			Rigidbody[] componentsInChildren = ((Component)((Component)unit).transform.root).GetComponentsInChildren<Rigidbody>(true);
			HashSet<Transform> hashSet = new HashSet<Transform>();
			Rigidbody[] array = componentsInChildren;
			foreach (Rigidbody val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.position += delta;
					hashSet.Add(((Component)val).transform);
				}
			}
			if (rotateBodyChildren && (Object)(object)unit.data != (Object)null)
			{
				for (int j = 0; j < ((Component)unit.data).transform.childCount; j++)
				{
					((Component)unit.data).transform.GetChild(j).Rotate(Vector3.up * 180f);
				}
			}
			PhysicsFollowBodyPart[] componentsInChildren2 = ((Component)((Component)unit).transform.root).GetComponentsInChildren<PhysicsFollowBodyPart>(true);
			foreach (PhysicsFollowBodyPart val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null) && !HasMovedRigidbodyParent(((Component)val2).transform, hashSet))
				{
					Transform transform = ((Component)val2).transform;
					transform.position += delta;
				}
			}
			MoveNonRigidbodyWeapon(unit.WeaponHandler?.rightWeapon, delta, hashSet);
			MoveNonRigidbodyWeapon(unit.WeaponHandler?.leftWeapon, delta, hashSet);
			if ((Object)(object)unit.data != (Object)null)
			{
				unit.data.currentVelocity = Vector3.zero;
				unit.data.lastPos = (((Object)(object)unit.data.mainRig != (Object)null) ? unit.data.mainRig.position : Vector3.zero);
				DataHandler data = unit.data;
				data.groundPosition += delta;
				DataHandler data2 = unit.data;
				data2.groundMapPosition += delta;
				DataHandler data3 = unit.data;
				data3.centerOfMass += delta;
				DataHandler data4 = unit.data;
				data4.centerOfMassWithoutY += new Vector3(delta.x, 0f, delta.z);
			}
			Physics.SyncTransforms();
		}

		private static void SnapFeetToGround(Unit unit, float groundY)
		{
			//IL_0029: 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)
			Physics.SyncTransforms();
			if (TryGetActualFootBottomY(unit, out var bottomY))
			{
				float num = groundY + 0.08f - bottomY;
				if (!(Mathf.Abs(num) < 0.005f))
				{
					MoveRagdollAsOne(unit, Vector3.up * num, rotateBodyChildren: false);
				}
			}
		}

		private static bool HasMovedRigidbodyParent(Transform transform, HashSet<Transform> movedTransforms)
		{
			Transform val = transform;
			while ((Object)(object)val != (Object)null)
			{
				if (movedTransforms.Contains(val))
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static void MoveNonRigidbodyWeapon(Weapon weapon, Vector3 delta, HashSet<Transform> movedTransforms)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: 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)
			if (!((Object)(object)weapon == (Object)null) && !HasMovedRigidbodyParent(((Component)weapon).transform, movedTransforms))
			{
				Transform transform = ((Component)weapon).transform;
				transform.position += delta;
			}
		}

		private static void RestoreRagdollAfterTeleport(Unit unit, List<RigidbodySnapshot> snapshots)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_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)
			foreach (RigidbodySnapshot snapshot in snapshots)
			{
				Rigidbody rigidbody = snapshot.Rigidbody;
				if (!((Object)(object)rigidbody == (Object)null))
				{
					rigidbody.isKinematic = snapshot.WasKinematic;
					if (!snapshot.WasKinematic)
					{
						rigidbody.velocity = Vector3.zero;
						rigidbody.angularVelocity = Vector3.zero;
					}
					rigidbody.detectCollisions = snapshot.DetectedCollisions;
				}
			}
			if ((Object)(object)unit != (Object)null && (Object)(object)unit.data != (Object)null && (Object)(object)unit.data.mainRig != (Object)null)
			{
				unit.data.currentVelocity = Vector3.zero;
				unit.data.lastPos = unit.data.mainRig.position;
			}
			Physics.SyncTransforms();
		}
	}
	[HarmonyPatch(typeof(UnitBlueprint), "DeserializedUnit", new Type[]
	{
		typeof(SerializedUnitBlueprint),
		typeof(AssetLoader),
		typeof(LandfallContentDatabase)
	})]
	internal static class AssassinPoofLegacyLoadPatch
	{
		private static void Prefix(SerializedUnitBlueprint data, LandfallContentDatabase landfallContentDatabase)
		{
			AssassinPoofCompatibility.MigrateLegacyAbility(data, landfallContentDatabase);
		}
	}
	[HarmonyPatch(typeof(UnitBlueprint), "SerializedUnit", new Type[] { typeof(DatabaseID) })]
	internal static class AssassinPoofVanillaSavePatch
	{
		private static void Postfix(SerializedUnitBlueprint __result)
		{
			AssassinPoofCompatibility.MigrateLegacyAbility(__result);
		}
	}
	[HarmonyPatch(typeof(AssassinPoofEffect), "Start")]
	internal static class NativeAssassinPoofStartOverridePatch
	{
		private static bool Prefix(AssassinPoofEffect __instance)
		{
			return !AssassinPoofCompatibility.TryAttachToSpawnedUnit(__instance);
		}
	}
	[HarmonyPatch(typeof(AssassinPoofEffect), "Update")]
	internal static class NativeAssassinPoofUpdateOverridePatch
	{
		private static bool Prefix(AssassinPoofEffect __instance)
		{
			return !AssassinPoofCompatibility.TryAttachToSpawnedUnit(__instance);
		}
	}
	[HarmonyPatch(typeof(AssassinPoofEffect), "DoThePoof")]
	internal static class NativeAssassinPoofManualOverridePatch
	{
		private static bool Prefix(AssassinPoofEffect __instance)
		{
			return !AssassinPoofCompatibility.TryAttachToSpawnedUnit(__instance);
		}
	}
	[BepInPlugin("fero.tabs.better_tracing", "Better Tracing", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class BetterTracingPlugin : BaseUnityPlugin
	{
		public const string PluginGuid = "fero.tabs.better_tracing";

		private const string SettingKey = "Better Tracing";

		private ConfigEntry<bool> _enabled;

		private Harmony _harmony;

		private SettingsInstance _setting;

		internal static BetterTracingPlugin Instance { get; private set; }

		internal static bool IsEnabled()
		{
			if ((Object)(object)Instance != (Object)null)
			{
				return Instance._enabled?.Value ?? false;
			}
			return false;
		}

		internal static void LogPluginInfo(string message)
		{
			BetterTracingPlugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogInfo((object)message);
			}
		}

		internal static void LogPluginWarning(string message)
		{
			BetterTracingPlugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Logger.LogWarning((object)message);
			}
		}

		private void Awake()
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			Instance = this;
			_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Gameplay", "BetterTracing", true, "Help units navigate obstacles and protect fast-moving ragdolls from tunnelling through terrain.");
			_harmony = new Harmony("fero.tabs.better_tracing");
			int num = 0;
			Type[] types = typeof(BetterTracingPlugin).Assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Any())
				{
					try
					{
						_harmony.CreateClassProcessor(type).Patch();
						num++;
					}
					catch (Exception ex)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not patch " + type.Name + ": " + ex.Message));
					}
				}
			}
			((MonoBehaviour)this).StartCoroutine(InjectSettingWhenReady());
			((MonoBehaviour)this).StartCoroutine(InstallRuntimeWhenReady());
			SpawnerAbilityRegistry.EnsureRegistered();
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Better Tracing loaded ({num} patch classes). Personal Assassin Poof: {AssassinPoofCompatibility.PersonalOverrideEnabled}.");
		}

		private IEnumerator InstallRuntimeWhenReady()
		{
			yield return null;
			try
			{
				TechnicalAbilityRuntime.Install(_harmony);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not enable optional Technical Items settings: " + ex.Message));
			}
			try
			{
				FleeDistanceRuntime.Install(_harmony);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Per-unit Flee Distance stats enabled.");
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not enable Flee Distance stats: " + ex2.Message));
			}
			try
			{
				UnitBehaviourRuntime.Install(_harmony);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Per-unit movement and targeting stats enabled.");
			}
			catch (Exception ex3)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not enable movement/targeting stats: " + ex3.Message));
			}
			try
			{
				foreach (UnitBlueprint userUnitBlueprint in ContentDatabase.Instance().GetUserUnitBlueprints())
				{
					SavedUnitSelection.RestoreWeaponFile(userUnitBlueprint);
				}
			}
			catch (Exception ex4)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not recover early-loaded weapon settings: " + ex4.Message));
			}
		}

		private IEnumerator InjectSettingWhenReady()
		{
			for (int i = 0; i < 1200; i++)
			{
				GlobalSettingsHandler service = ServiceLocator.GetService<GlobalSettingsHandler>();
				if ((Object)(object)service != (Object)null)
				{
					InjectSetting(service);
					break;
				}
				yield return null;
			}
		}

		internal static void InjectSetting(GlobalSettingsHandler handler)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Instance == (Object)null) && !((Object)(object)handler == (Object)null))
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(GlobalSettingsHandler), "m_gameplaySettings");
				List<SettingsInstance> list = (((SettingsInstance[])fieldInfo.GetValue(handler)) ?? Array.Empty<SettingsInstance>()).ToList();
				Instance._setting = ((IEnumerable<SettingsInstance>)list).FirstOrDefault((Func<SettingsInstance, bool>)((SettingsInstance s) => s?.m_settingsKey == "Better Tracing"));
				if (Instance._setting == null)
				{
					BetterTracingPlugin instance = Instance;
					SettingsInstance val = new SettingsInstance();
					val.settingsType = (SettingsType)0;
					val.options = new string[2] { "On", "Off" };
					val.defaultValue = 0;
					val.m_settingsKey = "Better Tracing";
					val.settingName = "Better Tracing";
					val.toolTip = "Helps units move around obstacles and prevents fast units from passing through terrain";
					instance._setting = val;
					list.Add(Instance._setting);
					fieldInfo.SetValue(handler, list.ToArray());
				}
				Instance._setting.currentValue = ((!IsEnabled()) ? 1 : 0);
				Instance._setting.OnValueChanged -= Instance.SetEnabled;
				Instance._setting.OnValueChanged += Instance.SetEnabled;
				if (AccessTools.Field(typeof(GlobalSettingsHandler), "m_settingsDict")?.GetValue(handler) is Dictionary<string, SettingsInstance> dictionary)
				{
					dictionary["Better Tracing"] = Instance._setting;
				}
			}
		}

		private void SetEnabled(int value)
		{
			_enabled.Value = value == 0;
			((BaseUnityPlugin)this).Config.Save();
		}

		internal static void OnSettingChanged(SettingsInstance setting)
		{
			if (setting?.m_settingsKey == "Better Tracing")
			{
				Instance?.SetEnabled(setting.currentValue);
			}
		}

		private void OnDestroy()
		{
			SpawnerAbilityEditor.CancelIfOpen();
			if (_setting != null)
			{
				_setting.OnValueChanged -= SetEnabled;
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			TracingGeometry.ReleaseQueryCollider();
			FormationUI.ReleaseAssets();
			Instance = null;
		}
	}
	[HarmonyPatch(typeof(GlobalSettingsHandler), "Init", new Type[] { typeof(bool) })]
	internal static class BetterTracingSettingsInitPatch
	{
		private static void Postfix(GlobalSettingsHandler __instance)
		{
			BetterTracingPlugin.InjectSetting(__instance);
		}
	}
	[HarmonyPatch(typeof(MenuSettingsButton), "UpdateValue", new Type[] { typeof(int) })]
	internal static class BetterTracingSettingsValuePatch
	{
		private static void Postfix(MenuSettingsButton __instance)
		{
			BetterTracingPlugin.OnSettingChanged((__instance != null) ? __instance.settingsInstance : null);
		}
	}
	internal sealed class CompanionUnitSession
	{
		internal readonly FormationMember Member;

		internal readonly UnitBlueprint Source;

		private readonly UnitFormation _formation;

		private readonly DatabaseID _parent;

		private readonly DatabaseID _unit;

		private string _copy;

		private string _stats;

		private string _abilities;

		private string _equipment;

		internal CompanionUnitSession(UnitFormation formation, int index, DatabaseID parent)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if (formation?.units == null || index < 0 || index >= formation.units.Count || formation.units[index] == null)
			{
				throw new ArgumentException("This added unit is no longer available.");
			}
			_formation = formation;
			Member = formation.units[index];
			_parent = parent;
			_unit = Member.unit;
			Source = UnitFormationData.ResolveMember(Member);
			UnitBlueprint source = Source;
			if (((source != null) ? source.Entity : null) == null || (Object)(object)Source.UnitBase == (Object)null)
			{
				throw new InvalidOperationException("This added unit is unavailable.");
			}
			Remember();
		}

		internal bool Allows(UnitBlueprint unit)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (((unit != null) ? unit.Entity : null) != null && (Object)(object)unit.UnitBase != (Object)null)
			{
				return !UnitFormationData.WouldCreateCycle(unit, _parent);
			}
			return false;
		}

		internal bool Save(UnitFormation current, UnitBlueprint edited)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			if (current == _formation)
			{
				List<FormationMember> units = current.units;
				if (units != null && units.Contains(Member) && !(Member.unit != _unit) && !(Member.copyJson != _copy) && !(Member.statsJson != _stats) && !(Member.abilitiesJson != _abilities) && !(Member.equipmentJson != _equipment) && Allows(edited))
				{
					string equipmentJson = JsonUtility.ToJson((object)new SerializedFormationEquipment
					{
						fullUnit = true,
						recipe = RiderRecipe.Capture(edited)
					});
					Member.equipmentJson = equipmentJson;
					Member.abilitiesJson = null;
					UnitFormationStats.Commit(Member, null);
					FormationEquipmentData.Invalidate(Member);
					Remember();
					return true;
				}
			}
			return false;
		}

		private void Remember()
		{
			_copy = Member.copyJson;
			_stats = Member.statsJson;
			_abilities = Member.abilitiesJson;
			_equipment = Member.equipmentJson;
		}
	}
	internal sealed class EditorTestCycle
	{
		private int _start = -10;

		private int _stop = -10;

		internal bool Start(bool testing, int frame)
		{
			if (testing || frame == _start || frame <= _stop + 1)
			{
				return false;
			}
			_start = frame;
			return true;
		}

		internal bool Stop(bool testing, int frame)
		{
			if (!testing || frame == _stop)
			{
				return false;
			}
			_stop = frame;
			return true;
		}
	}
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	public struct MeleeDistanceMovement : IMovementComponent, IComponentData
	{
	}
	internal static class ExtraStatsCompatibility
	{
		internal static string MovementTypeName(string savedTypeName)
		{
			if (string.IsNullOrWhiteSpace(savedTypeName))
			{
				return savedTypeName;
			}
			int num = savedTypeName.IndexOf(',');
			if (num < 0 || !string.Equals(savedTypeName.Substring(0, num).Trim(), typeof(MeleeDistanceMovement).FullName, StringComparison.Ordinal))
			{
				return savedTypeName;
			}
			return typeof(MeleeDistanceMovement).AssemblyQualifiedName;
		}
	}
	internal sealed class FactionBarRecovery : MonoBehaviour
	{
		private static readonly FieldInfo Bar = AccessTools.Field(typeof(PlacementUI), "factionBar");

		private static readonly FieldInfo Buttons = AccessTools.Field(typeof(PlacementFactionBar), "factionButtons");

		private static readonly FieldInfo SelectedFaction = AccessTools.Field(typeof(PlacementUI), "m_selectedFaction");

		private static readonly FieldInfo SelectedUnit = AccessTools.Field(typeof(PlacementUI), "m_lastSelectedUnit");

		private static readonly FieldInfo UnitLayout = AccessTools.Field(typeof(PlacementUI), "unitLayoutGroup");

		private static readonly FieldInfo Follow = AccessTools.Field(typeof(FactionButton), "lerpTargetTransform");

		private static readonly FieldInfo Velocity = AccessTools.Field(typeof(FactionButtonPhlerp), "velocity");

		private static readonly FieldInfo SpringTarget = AccessTools.Field(typeof(FactionButtonPhlerp), "target");

		private PlacementUI _owner;

		private PlacementFactionBar _bar;

		private DatabaseID[] _expected = Array.Empty<DatabaseID>();

		private DatabaseID _selectedFaction;

		private DatabaseID _selectedUnit;

		private bool _known;

		private bool _pending;

		private bool _redraw;

		private bool _repairing;

		private bool _restore;

		private int _frame;

		private int _spawning;

		private int _attempts;

		private List<FactionButton> Current => Buttons.GetValue(_bar) as List<FactionButton>;

		internal static FactionBarRecovery Of(PlacementUI owner)
		{
			PlacementFactionBar val = (PlacementFactionBar)(((Object)(object)owner == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			FactionBarRecovery component = ((Component)val).GetComponent<FactionBarRecovery>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			component = ((Component)val).gameObject.AddComponent<FactionBarRecovery>();
			component._owner = owner;
			component._bar = val;
			val.OnFactionBarChanged = (Action)Delegate.Combine(val.OnFactionBarChanged, new Action(component.SelectionChanged));
			return component;
		}

		private static FactionBarRecovery Of(PlacementFactionBar bar)
		{
			if ((Object)(object)bar == (Object)null)
			{
				return null;
			}
			FactionBarRecovery component = ((Component)bar).GetComponent<FactionBarRecovery>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			return Of(((IEnumerable<PlacementUI>)((Component)bar).GetComponentsInParent<PlacementUI>(true)).FirstOrDefault((Func<PlacementUI, bool>)delegate(PlacementUI ui)
			{
				object? value = Bar.GetValue(ui);
				return (Object)((value is PlacementFactionBar) ? value : null) == (Object)(object)bar;
			}));
		}

		internal static bool BeforeRedraw(PlacementUI owner)
		{
			FactionBarRecovery factionBarRecovery = Of(owner);
			if ((Object)(object)factionBarRecovery == (Object)null || factionBarRecovery._repairing)
			{
				return true;
			}
			factionBarRecovery.Queue();
			if (((Behaviour)factionBarRecovery._bar).isActiveAndEnabled)
			{
				return true;
			}
			factionBarRecovery.RememberSelection();
			factionBarRecovery._redraw = true;
			return false;
		}

		internal static void CheckAfterReturn(PlacementUI owner)
		{
			Of(owner)?.Queue();
		}

		internal static FactionBarRecovery BeforeSpawn(PlacementFactionBar bar, ref Faction[] factions)
		{
			FactionBarRecovery factionBarRecovery = Of(bar);
			if ((Object)(object)factionBarRecovery == (Object)null)
			{
				return null;
			}
			GameModeService service = ServiceLocator.GetService<GameModeService>();
			bool online = ((service != null) ? service.CurrentGameMode : null) is OnlineMultiplayerGameMode;
			Faction[] array = ((IEnumerable<Faction>)((online ? ((object)ContentDatabase.Instance().GetDefaultHotbarFactions().ToArray()) : ((object)factions)) ?? Array.Empty<Faction>())).Where((Faction faction) => Renderable(faction) && (!online || (!faction.IsCustom && !faction.IsModFaction))).ToArray();
			factionBarRecovery._expected = array.Select((Faction faction) => faction.Entity.GUID).ToArray();
			factionBarRecovery._known = true;
			if (!online)
			{
				factions = array;
			}
			factionBarRecovery._spawning++;
			return factionBarRecovery;
		}

		private static bool Renderable(Faction faction)
		{
			if ((Object)(object)faction != (Object)null && faction.Entity != null && faction.Units != null)
			{
				return faction.Units.All((UnitBlueprint unit) => (Object)(object)unit != (Object)null && !unit.HasMissingComponents);
			}
			return false;
		}

		internal void AfterSpawn()
		{
			_spawning = Math.Max(0, _spawning - 1);
			if (!_repairing)
			{
				Queue();
			}
		}

		private void SelectionChanged()
		{
			if (_spawning != 0 || _repairing)
			{
				return;
			}
			_expected = (from button in (Current ?? new List<FactionButton>()).Where(delegate(FactionButton button)
				{
					if ((Object)(object)button != (Object)null)
					{
						Faction faction = button.faction;
						return ((faction != null) ? faction.Entity : null) != null;
					}
					return false;
				})
				select button.faction.Entity.GUID).ToArray();
			_known = true;
			Queue();
		}

		private void Queue()
		{
			_pending = true;
			_frame = Time.frameCount + 2;
			_attempts = 0;
		}

		private void RememberSelection()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			if (!_restore)
			{
				object? value = SelectedFaction.GetValue(_owner);
				object? obj = ((value is Faction) ? value : null);
				DatabaseID? obj2;
				if (obj == null)
				{
					obj2 = null;
				}
				else
				{
					DatabaseEntity entity = ((Faction)obj).Entity;
					obj2 = ((entity != null) ? new DatabaseID?(entity.GUID) : ((DatabaseID?)null));
				}
				DatabaseID? val = obj2;
				_selectedFaction = val.GetValueOrDefault();
				_selectedUnit = (DatabaseID)SelectedUnit.GetValue(_owner);
				_restore = true;
			}
		}

		private static bool Finite(Vector3 value)
		{
			//IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			if (Finite(value.x) && Finite(value.y))
			{
				return Finite(value.z);
			}
			return false;
		}

		private static bool Finite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		private bool RepairButtons()
		{
			//IL_005d: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			List<FactionButton> current = Current;
			if (!_known)
			{
				return true;
			}
			if (current == null || current.Count != _expected.Length)
			{
				return false;
			}
			for (int i = 0; i < current.Count; i++)
			{
				FactionButton val = current[i];
				if (!((Object)(object)val == (Object)null))
				{
					Faction faction = val.faction;
					if (((faction != null) ? faction.Entity : null) != null && !(val.faction.Entity.GUID != _expected[i]) && !((Object)(object)((Component)val).transform.parent != (Object)(object)_bar.RealObjectParent))
					{
						Transform followTransform = val.GetFollowTransform();
						if ((Object)(object)followTransform == (Object)null || !followTransform.IsChildOf(_bar.FollowTransformParent) || !Finite(followTransform.position))
						{
							return false;
						}
						BindIcon(val);
						FactionButtonPhlerp component = ((Component)val).GetComponent<FactionButtonPhlerp>();
						if (((Component)val).gameObject.activeSelf && ((Behaviour)val).enabled && Finite(((Component)val).transform.position) && Finite(((Component)val).transform.localScale))
						{
							Vector3 val2 = ((Component)val).transform.localScale;
							if (!(((Vector3)(ref val2)).sqrMagnitude < 0.0001f))
							{
								val2 = ((Component)val).transform.position - followTransform.position;
								if (!(((Vector3)(ref val2)).sqrMagnitude > 4096f) && !((Object)(object)component == (Object)null) && ((Behaviour)component).enabled && Finite((Vector3)Velocity.GetValue(component)) && !((Object)/*isinst with value type is only supported in some contexts*/ != (Object)(object)followTransform))
								{
									continue;
								}
							}
						}
						((Component)val).gameObject.SetActive(true);
						((Behaviour)val).enabled = true;
						((Component)val).transform.position = followTransform.position;
						((Component)val).transform.localScale = _bar.prefab.transform.localScale;
						Follow.SetValue(val, followTransform);
						val.SetupPhlerp();
						Velocity.SetValue(((Component)val).GetComponent<FactionButtonPhlerp>(), Vector3.zero);
						continue;
					}
				}
				return false;
			}
			return true;
		}

		private static void BindIcon(FactionButton button)
		{
			Faction faction = button.faction;
			faction.Entity.GetSpriteIconAsync((Action<Sprite>)delegate(Sprite sprite)
			{
				if (!((Object)(object)button == (Object)null) && !((Object)(object)button.faction != (Object)(object)faction) && !((Object)(object)button.m_Image == (Object)null) && !((Object)(object)sprite == (Object)null))
				{
					button.m_Image.sprite = sprite;
					((Behaviour)button.m_Image).enabled = true;
				}
			});
		}

		private void RestoreSelection()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if (!_restore)
			{
				return;
			}
			_restore = false;
			FactionButton val = Current?.FirstOrDefault((Func<FactionButton, bool>)delegate(FactionButton item)
			{
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)item != (Object)null)
				{
					Faction faction = item.faction;
					DatabaseID? obj2;
					if (faction == null)
					{
						obj2 = null;
					}
					else
					{
						DatabaseEntity entity = faction.Entity;
						obj2 = ((entity != null) ? new DatabaseID?(entity.GUID) : ((DatabaseID?)null));
					}
					DatabaseID? val3 = obj2;
					DatabaseID selectedFaction = _selectedFaction;
					if (!val3.HasValue)
					{
						return false;
					}
					return val3.GetValueOrDefault() == selectedFaction;
				}
				return false;
			});
			if (!((Object)(object)val == (Object)null) && ((SimpleButton)val).Unlocked)
			{
				_owner.SelectFaction(_selectedFaction, val);
				object? value = UnitLayout.GetValue(_owner);
				object? obj = ((value is UILayoutGroup) ? value : null);
				UnitButton val2 = ((obj != null) ? ((UILayoutGroup)obj).GetUnitButton(_selectedUnit) : null);
				if ((Object)(object)val2 != (Object)null && ((SimpleButton)val2).Unlocked)
				{
					_owner.SelectUnit(_selectedUnit, val2);
				}
			}
		}

		private void LateUpdate()
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Invalid comparison between Unknown and I4
			if (!_pending || (Object)(object)_owner == (Object)null || (Object)(object)_bar == (Object)null || Time.frameCount < _frame || !((UIComponentBase)_owner).IsActive || !((Behaviour)_bar).isActiveAndEnabled)
			{
				return;
			}
			GameStateManager service = ServiceLocator.GetService<GameStateManager>();
			if (service == null || (int)service.GameState > 0)
			{
				return;
			}
			try
			{
				Canvas.ForceUpdateCanvases();
				if (_redraw || !RepairButtons())
				{
					if (++_attempts > 3)
					{
						_pending = false;
						BetterTracingPlugin.LogPluginWarning("Faction bar could not finish rebuilding; saved faction choices were preserved.");
						return;
					}
					RememberSelection();
					_repairing = true;
					try
					{
						_owner.RedrawFactions();
						_redraw = false;
					}
					finally
					{
						_repairing = false;
					}
					_frame = Time.frameCount + 2;
				}
				else
				{
					RestoreSelection();
					_pending = false;
				}
			}
			catch (Exception ex)
			{
				_repairing = false;
				_frame = Time.frameCount + 2;
				if (++_attempts > 3)
				{
					_pending = false;
					BetterTracingPlugin.LogPluginWarning("Could not restore the faction bar: " + ex.Message);
				}
			}
		}

		private void OnDestroy()
		{
			if ((Object)(object)_bar != (Object)null)
			{
				PlacementFactionBar bar = _bar;
				bar.OnFactionBarChanged = (Action)Delegate.Remove(bar.OnFactionBarChanged, new Action(SelectionChanged));
			}
		}
	}
	[HarmonyPatch(typeof(PlacementUI), "RedrawFactions")]
	internal static class FactionBarRedrawPatch
	{
		private static bool Prefix(PlacementUI __instance)
		{
			return FactionBarRecovery.BeforeRedraw(__instance);
		}
	}
	[HarmonyPatch(typeof(PlacementUI), "EnterPlacementState")]
	internal static class FactionBarReturnPatch
	{
		private static void Postfix(PlacementUI __instance)
		{
			FactionBarRecovery.CheckAfterReturn(__instance);
		}
	}
	[HarmonyPatch(typeof(PlacementUI), "OnOpen")]
	internal static class FactionBarOpenPatch
	{
		private static void Postfix(PlacementUI __instance)
		{
			FactionBarRecovery.CheckAfterReturn(__instance);
		}
	}
	[HarmonyPatch(typeof(PlacementFactionBar), "Spawn", new Type[]
	{
		typeof(Faction[]),
		typeof(bool)
	})]
	internal static class FactionBarSpawnPatch
	{
		private static void Prefix(PlacementFactionBar __instance, ref Faction[] factions, out FactionBarRecovery __state)
		{
			__state = FactionBarRecovery.BeforeSpawn(__instance, ref factions);
		}

		private static Exception Finalizer(FactionBarRecovery __state, Exception __exception)
		{
			__state?.AfterSpawn();
			return __exception;
		}
	}
	[DefaultExecutionOrder(12000)]
	internal sealed class FastUnitCollisionGuard : MonoBehaviour
	{
		private sealed class Body
		{
			internal Rigidbody Rig;

			internal Collider Collider;

			internal bool HasPrevious;

			internal Vector3 PreviousCenter;

			internal float PreviousSpeed;

			internal bool Core;
		}

		private readonly List<Body> _bodies = new List<Body>();

		private readonly RaycastHit[] _hits = (RaycastHit[])(object)new RaycastHit[48];

		private Unit _unit;

		private Rigidbody[] _rigs;

		private Vector3[] _positions;

		internal void Initialize(Unit unit)
		{
			ResetSweep();
			_unit = unit;
			_bodies.Clear();
			if ((Object)(object)unit == (Object)null)
			{
				return;
			}
			_rigs = ((Component)unit).GetComponentsInChildren<Rigidbody>(true);
			_positions = (Vector3[])(object)new Vector3[_rigs.Length];
			Rigidbody[] rigs = _rigs;
			foreach (Rigidbody val in rigs)
			{
				if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).GetComponentInParent<Unit>() != (Object)(object)unit || (Object)(object)((Component)val).GetComponentInParent<Holdable>() != (Object)null)
				{
					continue;
				}
				Collider val2 = null;
				Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren<Collider>(true);
				foreach (Collider val3 in componentsInChildren)
				{
					if (!((Object)(object)val3.attachedRigidbody != (Object)(object)val) && !val3.isTrigger && (val3 is SphereCollider || val3 is CapsuleCollider || val3 is BoxCollider))
					{
						val2 = val3;
						break;
					}
				}
				if (!((Object)(object)val2 == (Object)null))
				{
					_bodies.Add(new Body
					{
						Rig = val,
						Collider = val2,
						Core = ((Object)(object)val == (Object)(object)unit.data?.mainRig || (Object)(object)((Component)val).transform == (Object)(object)unit.data?.torso || (Object)(object)((Component)val).transform == (Object)(object)unit.data?.head)
					});
				}
			}
		}

		private void FixedUpdate()
		{
			//IL_0021: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: 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_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: 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_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Unknown result type (might be due to invalid IL or missing references)
			//IL_033d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: 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_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			if (!BetterTracingPlugin.IsEnabled() || !TracingGeometry.IsLocallyControlled(_unit))
			{
				ResetSweep();
				return;
			}
			float num = 1f;
			Vector3 val = Vector3.zero;
			Vector3 normal = Vector3.zero;
			Bounds bounds;
			Vector3 velocity;
			foreach (Body body in _bodies)
			{
				Rigidbody rig = body.Rig;
				if ((Object)(object)rig == (Object)null || (Object)(object)body.Collider == (Object)null || !body.Collider.enabled || rig.isKinematic || !rig.detectCollisions)
				{
					body.HasPrevious = false;
					continue;
				}
				bounds = body.Collider.bounds;
				Vector3 center = ((Bounds)(ref bounds)).center;
				bounds = body.Collider.bounds;
				Vector3 extents = ((Bounds)(ref bounds)).extents;
				float num2 = Mathf.Clamp(Mathf.Min(extents.x, Mathf.Min(extents.y, extents.z)) * 0.75f, 0.035f, 0.75f);
				velocity = rig.velocity;
				float magnitude = ((Vector3)(ref velocity)).magnitude;
				if (!body.Core || !body.HasPrevious || !IsPhysicalStep(body.PreviousCenter, center, body.PreviousSpeed, magnitude, Time.fixedDeltaTime, num2))
				{
					continue;
				}
				Vector3 val2 = center - body.PreviousCenter;
				float magnitude2 = ((Vector3)(ref val2)).magnitude;
				int num3 = Physics.SphereCastNonAlloc(body.PreviousCenter, num2, val2 / magnitude2, _hits, magnitude2, -1, (QueryTriggerInteraction)1);
				RaycastHit[] array = ((num3 == _hits.Length) ? Physics.SphereCastAll(body.PreviousCenter, num2, val2 / magnitude2, magnitude2, -1, (QueryTriggerInteraction)1) : _hits);
				if (array != _hits)
				{
					num3 = array.Length;
				}
				for (int i = 0; i < num3; i++)
				{
					RaycastHit val3 = array[i];
					if (TracingGeometry.IsEnvironment(((RaycastHit)(ref val3)).collider, _unit, body.Collider) && !(((RaycastHit)(ref val3)).distance <= 0.001f) && CrossedSurface(body.PreviousCenter, center, ((RaycastHit)(ref val3)).point, ((RaycastHit)(ref val3)).normal))
					{
						float num4 = Mathf.Clamp01((((RaycastHit)(ref val3)).distance - 0.02f) / magnitude2);
						if (!(num4 >= num))
						{
							num = num4;
							val = body.PreviousCenter + val2 * num4 - center;
							normal = ((RaycastHit)(ref val3)).normal;
						}
					}
				}
			}
			if (num < 1f && TracingGeometry.IsFinite(val))
			{
				RecoverRagdoll(val, normal);
			}
			foreach (Body body2 in _bodies)
			{
				body2.HasPrevious = (Object)(object)body2.Rig != (Object)null && (Object)(object)body2.Collider != (Object)null && body2.Collider.enabled && !body2.Rig.isKinematic && body2.Rig.detectCollisions;
				if (body2.HasPrevious)
				{
					bounds = body2.Collider.bounds;
					body2.PreviousCenter = ((Bounds)(ref bounds)).center;
					velocity = body2.Rig.velocity;
					body2.PreviousSpeed = ((Vector3)(ref velocity)).magnitude;
				}
			}
		}

		internal static bool IsPhysicalStep(Vector3 previous, Vector3 current, float previousSpeed, float currentSpeed, float deltaTime, float radius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (!TracingGeometry.IsFinite(previous) || !TracingGeometry.IsFinite(current) || float.IsNaN(previousSpeed) || float.IsInfinity(previousSpeed) || float.IsNaN(currentSpeed) || float.IsInfinity(currentSpeed) || deltaTime <= 0f)
			{
				return false;
			}
			Vector3 val = current - previous;
			float magnitude = ((Vector3)(ref val)).magnitude;
			float num = Mathf.Max(previousSpeed, currentSpeed) * deltaTime * 2f + 0.35f;
			if (magnitude > Mathf.Max(0.04f, radius * 0.5f))
			{
				return magnitude <= num;
			}
			return false;
		}

		internal static bool CrossedSurface(Vector3 previous, Vector3 current, Vector3 point, Vector3 normal)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_0024: 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)
			if (((Vector3)(ref normal)).sqrMagnitude > 0.5f && Vector3.Dot(previous - point, normal) > 0.01f)
			{
				return Vector3.Dot(current - point, normal) < -0.01f;
			}
			return false;
		}

		internal static Vector3 RemoveInwardVelocity(Vector3 velocity, Vector3 normal)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			float num = Vector3.Dot(velocity, normal);
			if (!(num < 0f))
			{
				return velocity;
			}
			return velocity - normal * num;
		}

		private void RecoverRagdoll(Vector3 correction, Vector3 normal)
		{
			//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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: 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_00a9: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < _rigs.Length; i++)
			{
				if ((Object)(object)_rigs[i] != (Object)null)
				{
					_positions[i] = _rigs[i].position;
				}
			}
			Transform transform = ((Component)_unit).transform;
			transform.position += correction;
			for (int j = 0; j < _rigs.Length; j++)
			{
				Rigidbody val = _rigs[j];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).GetComponentInParent<Unit>() != (Object)(object)_unit))
				{
					val.position = _positions[j] + correction;
					if (!val.isKinematic)
					{
						val.velocity = RemoveInwardVelocity(val.velocity, normal);
					}
				}
			}
			Physics.SyncTransforms();
		}

		private void ResetSweep()
		{
			foreach (Body body in _bodies)
			{
				body.HasPrevious = false;
			}
		}

		private void OnDisable()
		{
			ResetSweep();
		}

		private void OnDestroy()
		{
			ResetSweep();
		}
	}
	internal sealed class FleeDistanceEditorData
	{
		internal FleeDistanceSettings Settings;

		internal float DefaultDistance;

		internal FleeDistanceSettings Defaults => new FleeDistanceSettings
		{
			distance = DefaultDistance
		};

		internal FleeDistanceSettings Effective => Settings?.Clone() ?? Defaults;
	}
	internal static class FleeDistanceData
	{
		internal const string JsonKey = "betterTracingFleeDistance";

		private static readonly ConditionalWeakTable<UnitBlueprint, FleeDistanceSettings> Blueprints = new ConditionalWeakTable<UnitBlueprint, FleeDistanceSettings>();

		private static readonly ConditionalWeakTable<UnitEditorManager, FleeDistanceEditorData> Editors = new ConditionalWeakTable<UnitEditorManager, FleeDistanceEditorData>();

		private static readonly ConditionalWeakTable<SerializedUnitBlueprint, FleeDistanceSettings> Serialized = new ConditionalWeakTable<SerializedUnitBlueprint, FleeDistanceSettings>();

		[ThreadStatic]
		private static FleeDistanceSettings s_snapshot;

		[ThreadStatic]
		private static DatabaseID s_snapshotId;

		internal static bool HasFlee(UnitBlueprint unit)
		{
			if (unit == null)
			{
				return false;
			}
			return unit.MovementComponents?.Any((IMovementComponent component) => component is FleeDistance) == true;
		}

		internal static float NativeDistance(IEnumerable<IMovementComponent> components)
		{
			return (from component in components?.OfType<FleeDistance>()
				select component.Value).FirstOrDefault() ?? 0f;
		}

		internal static bool Selected(UnitEditorManager manager)
		{
			if ((Object)(object)manager == (Object)null)
			{
				return false;
			}
			int num = (int)(AccessTools.Field(typeof(UnitEditorManager), "currentMovementType")?.GetValue(manager) ?? ((object)(-1)));
			if (manager?.MovementTypesComponents != null && num >= 0 && num < manager.MovementTypesComponents.Count)
			{
				return manager.MovementTypesComponents[num] is FleeDistance;
			}
			return false;
		}

		internal static FleeDistanceEditorData ForEditor(UnitEditorManager manager)
		{
			return Editors.GetValue(manager, (UnitEditorManager owner) => new FleeDistanceEditorData
			{
				DefaultDistance = NativeDistance(owner.MovementTypesComponents)
			});
		}

		internal static FleeDistanceSettings Get(UnitBlueprint unit)
		{
			if (!((Object)(object)unit != (Object)null) || !Blueprints.TryGetValue(unit, out var value))
			{
				return null;
			}
			return value;
		}

		internal static void Set(UnitBlueprint unit, FleeDistanceSettings data)
		{
			if ((Object)(object)unit == (Object)null)
			{
				return;
			}
			Blueprints.Remove(unit);
			if (data != null && HasFlee(unit))
			{
				data = data.Clone();
				Blueprints.Add(unit, data);
				unit.MovementComponents = unit.MovementComponents.Select((IMovementComponent component) => (IMovementComponent)((!(component is FleeDistance)) ? component : ((object)new FleeDistance
				{
					Value = data.distance
				}))).ToList();
			}
		}

		internal static void Copy(UnitBlueprint unit, UnitBlueprint source)
		{
			Set(unit, Get(source));
		}

		internal static void LoadEditor(UnitEditorManager manager, UnitBlueprint unit)
		{
			Editors.Remove(manager);
			Editors.Add(manager, new FleeDistanceEditorData
			{
				Settings = Get(unit)?.Clone(),
				DefaultDistance = NativeDistance(manager.MovementTypesComponents)
			});
			if (Get(unit) == null && HasFlee(unit))
			{
				ForEditor(manager).Settings = new FleeDistanceSettings
				{
					distance = NativeDistance(unit.MovementComponents)
				};
			}
		}

		internal static void ClearEditor(UnitEditorManager manager)
		{
			Editors.Remove(manager);
		}

		internal static void EditorBlueprint(UnitEditorManager manager, UnitBlueprint unit)
		{
			Set(unit, Selected(manager) ? ForEditor(manager).Settings : null);
		}

		internal static void CaptureSerialized(UnitBlueprint unit, SerializedUnitBlueprint serialized)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			s_snapshot = null;
			if (serialized != null)
			{
				Serialized.Remove(serialized);
				FleeDistanceSettings fleeDistanceSettings = Get(unit);
				if (fleeDistanceSettings != null)
				{
					Serialized.Add(serialized, fleeDistanceSettings.Clone());
					s_snapshot = fleeDistanceSettings.Clone();
					s_snapshotId = serialized.m_id;
				}
			}
		}

		internal static void ExtendJson(object value, ref string json)
		{
			//IL_0024: 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)
			SerializedUnitBlueprint val = (SerializedUnitBlueprint)((value is SerializedUnitBlueprint) ? value : null);
			if (val != null && !string.IsNullOrEmpty(json))
			{
				if (!Serialized.TryGetValue(val, out var value2) && val.m_id == s_snapshotId)
				{
					value2 = s_snapshot;
				}
				s_snapshot = null;
				int num = json.LastIndexOf('}');
				if (value2 != null && num >= 0)
				{
					json = json.Substring(0, num).TrimEnd(Array.Empty<char>()) + ",\n\"betterTracingFleeDistance\":" + JsonUtility.ToJson((object)value2) + "\n}";
				}
			}
		}

		internal static void ReadJson(string json, object value)
		{
			SerializedUnitBlueprint val = (SerializedUnitBlueprint)((value is SerializedUnitBlueprint) ? value : null);
			if (val == null)
			{
				return;
			}
			Serialized.Remove(val);
			try
			{
				string text = UnitFormationData.ExtractPayload(json, "betterTracingFleeDistance");
				FleeDistanceSettings fleeDistanceSettings = (string.IsNullOrEmpty(text) ? null : JsonUtility.FromJson<FleeDistanceSettings>(text));
				if (fleeDistanceSettings != null && fleeDistanceSettings.version == 1)
				{
					Serialized.Add(val, fleeDistanceSettings.Clone());
				}
			}
			catch (Exception ex)
			{
				BetterTracingPlugin.LogPluginWarning("Could not read Flee Distance settings: " + ex.Message);
			}
		}

		internal static void RestoreSerialized(SerializedUnitBlueprint serialized, UnitBlueprint unit)
		{
			Set(unit, (serialized != null && Serialized.TryGetValue(serialized, out var value)) ? value : null);
		}

		internal static void RestoreFileJson(UnitBlueprint unit, string json)
		{
			//IL_003f: 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)
			if (((unit != null) ? unit.Entity : null) != null && Get(unit) == null && HasFlee(unit) && !string.IsNullOrEmpty(json) && UnitFormationData.ExtractPayload(json, "betterTracingFleeDistance") != null)
			{
				SerializedUnitBlueprint val = JsonUtility.FromJson<SerializedUnitBlueprint>(json);
				if (val != null && !(val.m_id != unit.Entity.GUID))
				{
					ReadJson(json, val);
					RestoreSerialized(val, unit);
				}
			}
		}
	}
	internal sealed class FleeDistanceEditor : MonoBehaviour
	{
		internal UnitEditorManager Manager;

		internal FleeDistanceStatsPage Page;

		private UnitEditorUnitPage _owner;

		private Button _movement;

		private Button _button;

		private Canvas _canvas;

		private CanvasGroup _group;

		private CanvasGroup[] _parents;

		private Mask[] _masks;

		private RectMask2D[] _rectMasks;

		private FormationUI _ui;

		private readonly Vector3[] _corners = (Vector3[])(object)new Vector3[4];

		internal static FleeDistanceEditor Of(UnitEditorManager manager)
		{
			if (!((Object)(object)manager == (Object)null))
			{
				return ((Component)manager).GetComponent<FleeDistanceEditor>();
			}
			return null;
		}

		internal static void Ensure(UnitEditorBasePageUI page)
		{
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Expected O, but got Unknown
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_031c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_035f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			UnitEditorUnitPage componentInParent = ((Component)page).GetComponentInParent<UnitEditorUnitPage>();
			UnitEditorManager val = componentInParent?.manager ?? Object.FindObjectOfType<UnitEditorManager>();
			if ((Object)(object)val == (Object)null || (Object)(object)componentInParent == (Object)null)
			{
				return;
			}
			FleeDistanceEditor fleeDistanceEditor = Of(val) ?? ((Component)val).gameObject.AddComponent<FleeDistanceEditor>();
			fleeDistanceEditor.Manager = val;
			if ((Object)(object)fleeDistanceEditor._button != (Object)null && (Object)(object)fleeDistanceEditor._owner == (Object)(object)componentInParent)
			{
				return;
			}
			object? obj = AccessTools.Field(typeof(UnitEditorBasePageUI), "movementType")?.GetValue(page);
			UnitEditorSelectableItem val2 = (UnitEditorSelectableItem)((obj is UnitEditorSelectableItem) ? obj : null);
			Button val3 = (Button)(((Object)(object)val2 == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
			TabbedUIPage[] obj2 = AccessTools.Field(typeof(TabbedUIComponent), "TABS")?.GetValue(componentInParent) as TabbedUIPage[];
			object obj3;
			if (obj2 == null)
			{
				obj3 = null;
			}
			else
			{
				TabbedUIPage? obj4 = ((IEnumerable<TabbedUIPage>)obj2).FirstOrDefault((Func<TabbedUIPage, bool>)((TabbedUIPage tab) => tab.tabSubMenu is UnitEditorStatsPageUI));
				if (obj4 == null)
				{
					obj3 = null;
				}
				else
				{
					Toggle toggleTab = obj4.toggleTab;
					obj3 = ((toggleTab != null) ? ((IEnumerable<Image>)((Component)toggleTab).GetComponentsInChildren<Image>(true)).FirstOrDefault((Func<Image, bool>)((Image image) => ((Object)image).name == "Icon" && (Object)(object)image.sprite != (Object)null)) : null);
				}
			}
			Image val4 = (Image)obj3;
			if ((Object)(object)val3 == (Object)null || (Object)(object)val4 == (Object)null)
			{
				return;
			}
			if ((Object)(object)fleeDistanceEditor._button != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)fleeDistanceEditor._button).gameObject);
			}
			fleeDistanceEditor._owner = componentInParent;
			fleeDistanceEditor._movement = val3;
			fleeDistanceEditor._canvas = ((Component)val3).GetComponentInParent<Canvas>();
			if (!((Object)(object)fleeDistanceEditor._canvas == (Object)null))
			{
				fleeDistanceEditor._parents = ((Component)val3).GetComponentsInParent<CanvasGroup>(true);
				fleeDistanceEditor._masks = ((Component)val3).GetComponentsInParent<Mask>(true);
				fleeDistanceEditor._rectMasks = ((Component)val3).GetComponentsInParent<RectMask2D>(true);
				Graphic targetGraphic = ((Selectable)val3).targetGraphic;
				Image val5 = (Image)(object)((targetGraphic is Image) ? targetGraphic : null);
				fleeDistanceEditor._ui = new FormationUI(((Component)componentInParent).GetComponentInChildren<TMP_Text>(true), (val5 != null) ? val5.sprite : null, ((Component)val3).GetComponent<UISounds>());
				fleeDistanceEditor._button = fleeDistanceEditor._ui.Button("Flee Distance stats", ((Component)fleeDistanceEditor._canvas.rootCanvas).transform, "", new UnityAction(fleeDistanceEditor.Show));
				Image component = ((Component)fleeDistanceEditor._button).GetComponent<Image>();
				if ((Object)(object)val5 != (Object)null)
				{
					component.sprite = val5.sprite;
					component.type = val5.type;
					((Graphic)component).color = ((Graphic)val5).color;
					((Graphic)component).material = ((Graphic)val5).material;
					component.pixelsPerUnitMultiplier = val5.pixelsPerUnitMultiplier;
				}
				((Selectable)fleeDistanceEditor._button).colors = ((Selectable)val3).colors;
				((Selectable)fleeDistanceEditor._button).transition = ((Selectable)val3).transition;
				((Selectable)fleeDistanceEditor._button).spriteState = ((Selectable)val3).spriteState;
				Image obj5 = fleeDistanceEditor._ui.Panel("Stats icon", ((Component)fleeDistanceEditor._button).transform, Color.white, rounded: false);
				obj5.sprite = val4.sprite;
				obj5.type = val4.type;
				((Graphic)obj5).material = ((Graphic)val4).material;
				obj5.preserveAspect = true;
				((Graphic)obj5).raycastTarget = false;
				FormationUI.Stretch(((Graphic)obj5).rectTransform, new Vector2(16f, 16f), new Vector2(-16f, -16f));
				((RectTransform)((Component)fleeDistanceEditor._button).transform).pivot = new Vector2(1f, 0.5f);
				fleeDistanceEditor._group = ((Component)fleeDistanceEditor._button).gameObject.AddComponent<CanvasGroup>();
				((Component)fleeDistanceEditor._button).gameObject.AddComponent<LayoutElement>().ignoreLayout = true;
				((Component)fleeDistanceEditor._button).gameObject.SetActive(false);
			}
		}

		private Rect Bounds(RectTransform target, Transform parent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL