Decompiled source of StayCombatFix v1.1.0

StayCombatFix.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Landfall.TABS;
using Landfall.TABS.AI.Components;
using Landfall.TABS.GameState;
using Microsoft.CodeAnalysis;
using TFBGames;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Stay & Combat Fixes")]
[assembly: AssemblyDescription("Stay aura, lay-down combat, water physics, mirror shield, barrel death, gas grenade, and faction creator fixes for TABS")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Pretz")]
[assembly: AssemblyProduct("StayCombatFix")]
[assembly: AssemblyCopyright("Pretz")]
[assembly: ComVisible(false)]
[assembly: Guid("b2c3d4e5-f6a7-8901-bcde-f12345678901")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 StayCombatFix
{
	internal sealed class BarrelDeathPlan
	{
		internal Transform Root;

		internal float DelaySeconds;

		internal GameObject[] BarrelVisuals;

		internal Rigidbody[] BarrelRigidbodies;

		internal Transform[] BarrelAnchors;

		internal Vector3 SnapshotPosition;

		internal bool HasSnapshotPosition;

		internal Explosion CachedBarrelExplosion;

		internal GameObject CachedExplosionPrefab;

		internal Explosion FallbackExplosionTemplate;

		internal Unit OwnerUnit;
	}
	internal static class BarrelRollerDeathLogic
	{
		private struct PendingBarrelDeath
		{
			internal int RootId;

			internal BarrelDeathPlan Plan;

			internal float ExplodeAt;

			internal Vector3 ExplodePosition;

			internal bool HasExplodePosition;
		}

		[CompilerGenerated]
		private sealed class <ProcessDeathQueue>d__46 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <ProcessDeathQueue>d__46(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (PendingDeaths.Count > 0)
				{
					float time = Time.time;
					int num = 0;
					int num2 = PendingDeaths.Count - 1;
					while (num2 >= 0 && num < 8)
					{
						PendingBarrelDeath pendingBarrelDeath = PendingDeaths[num2];
						if (!(time < pendingBarrelDeath.ExplodeAt))
						{
							if ((Object)(object)pendingBarrelDeath.Plan?.Root == (Object)null)
							{
								PendingDeaths.RemoveAt(num2);
								PendingDeathRootIds.Remove(pendingBarrelDeath.RootId);
							}
							else
							{
								PendingDeaths.RemoveAt(num2);
								PendingDeathRootIds.Remove(pendingBarrelDeath.RootId);
								ExecuteDeathExplosion(pendingBarrelDeath.RootId, pendingBarrelDeath.Plan, pendingBarrelDeath.ExplodePosition, pendingBarrelDeath.HasExplodePosition);
								num++;
							}
						}
						num2--;
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				_queueRunner = null;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		internal const int BarrelRollerUnitId = 846602731;

		private const float MinimumDelaySeconds = 0.45f;

		private const float MaxBarrelDistanceFromUnit = 80f;

		private static MonoBehaviour _runner;

		private static ManualLogSource _log;

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

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

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

		private static readonly HashSet<int> KnownBarrelRollerRootIds = new HashSet<int>();

		private static readonly HashSet<int> NotBarrelRollerRootIds = new HashSet<int>();

		private static readonly List<PendingBarrelDeath> PendingDeaths = new List<PendingBarrelDeath>(32);

		private static readonly HashSet<int> PendingDeathRootIds = new HashSet<int>();

		private const float RecentBarrelExplosionWindowSeconds = 2.5f;

		private const float DuplicateAbilityExplosionWindowSeconds = 0.75f;

		private const float AbilityDeathSkipExplosionAgeSeconds = 0.5f;

		private const float AbilityExplosionOwnerSearchRadius = 20f;

		private const float DeathExplosionDamage = 15f;

		private const int MaxExplosionsPerFrame = 8;

		private static GameObject _sharedBarrelDeathExplosionPrefab;

		private static Explosion _sharedBarrelDeathExplosionTemplate;

		private static Coroutine _queueRunner;

		private static bool _executingDeathExplosion;

		internal static void Initialize(MonoBehaviour runner, ManualLogSource log)
		{
			_runner = runner;
			_log = log;
		}

		internal static void ResetBattleCaches()
		{
			RecentBarrelExplosionTimeByRoot.Clear();
			AllowedBarrelExplosionTimeByRoot.Clear();
			ActiveBarrelRollerRoots.Clear();
			KnownBarrelRollerRootIds.Clear();
			NotBarrelRollerRootIds.Clear();
			PendingDeaths.Clear();
			PendingDeathRootIds.Clear();
			_executingDeathExplosion = false;
			_queueRunner = null;
		}

		private static void EvictRootCache(int rootId)
		{
			KnownBarrelRollerRootIds.Remove(rootId);
			NotBarrelRollerRootIds.Remove(rootId);
			ActiveBarrelRollerRoots.Remove(rootId);
			RecentBarrelExplosionTimeByRoot.Remove(rootId);
			AllowedBarrelExplosionTimeByRoot.Remove(rootId);
			PendingDeathRootIds.Remove(rootId);
			for (int num = PendingDeaths.Count - 1; num >= 0; num--)
			{
				if (PendingDeaths[num].RootId == rootId)
				{
					PendingDeaths.RemoveAt(num);
				}
			}
		}

		private static bool IsCachedBarrelRollerRoot(Transform root, int rootId)
		{
			if (!KnownBarrelRollerRootIds.Contains(rootId))
			{
				return false;
			}
			if (!ActiveBarrelRollerRoots.TryGetValue(rootId, out var value) || (Object)(object)value == (Object)null)
			{
				EvictRootCache(rootId);
				return false;
			}
			if ((Object)(object)value != (Object)(object)root)
			{
				EvictRootCache(rootId);
				return false;
			}
			RememberBarrelRollerRoot(root);
			return true;
		}

		internal static void MarkRecentBarrelExplosion(Transform ownerRoot)
		{
			if (!((Object)(object)ownerRoot == (Object)null))
			{
				RecentBarrelExplosionTimeByRoot[((Object)ownerRoot).GetInstanceID()] = Time.time;
				CancelPendingDeathExplosion(ownerRoot);
			}
		}

		internal static void PrepareBarrelOwnedExplosionForDetonation(Explosion explosion)
		{
			if (!((Object)(object)explosion == (Object)null) && MightBeBarrelRollerExplosion(explosion))
			{
				Transform val = ResolveBarrelRollerOwnerRoot(((Component)explosion).transform);
				if (!((Object)(object)val == (Object)null) && IsBarrelRollerOwnedExplosion(explosion, val))
				{
					StripDeathExplosionStatusEffects(((Component)((Component)explosion).transform.root).gameObject);
				}
			}
		}

		internal static bool TryBlockDuplicateBarrelExplosion(Explosion explosion)
		{
			if ((Object)(object)explosion == (Object)null || _executingDeathExplosion || !MightBeBarrelRollerExplosion(explosion))
			{
				return false;
			}
			Transform val = ResolveBarrelRollerOwnerRoot(((Component)explosion).transform);
			if ((Object)(object)val == (Object)null || !IsBarrelRollerOwnedExplosion(explosion, val))
			{
				return false;
			}
			int instanceID = ((Object)val).GetInstanceID();
			float time = Time.time;
			if (AllowedBarrelExplosionTimeByRoot.TryGetValue(instanceID, out var value) && time - value <= 0.75f)
			{
				return true;
			}
			AllowedBarrelExplosionTimeByRoot[instanceID] = time;
			MarkRecentBarrelExplosion(val);
			return false;
		}

		private static bool MightBeBarrelRollerExplosion(Explosion explosion)
		{
			if ((Object)(object)explosion == (Object)null)
			{
				return false;
			}
			Transform transform = ((Component)explosion).transform;
			if ((Object)(object)transform == (Object)null)
			{
				return false;
			}
			if (IsRollingBarrelGearTransform(transform))
			{
				return true;
			}
			if (ContainsBarrelExplosionName(((Object)((Component)transform).gameObject).name) || ContainsBarrelExplosionName(((Object)transform.root).name))
			{
				return true;
			}
			int instanceID = ((Object)transform.root).GetInstanceID();
			return KnownBarrelRollerRootIds.Contains(instanceID);
		}

		internal static void NotifyBarrelAbilityExplosionFromSpawn(Transform scope, GameObject prefab)
		{
			if (!((Object)(object)scope == (Object)null) && !((Object)(object)prefab == (Object)null) && !_executingDeathExplosion && ContainsBarrelExplosionName(((Object)prefab).name))
			{
				Transform root = scope.root;
				if (IsBarrelRollerRoot(root))
				{
					MarkRecentBarrelExplosion(root);
				}
			}
		}

		private static void CancelPendingDeathExplosion(Transform ownerRoot)
		{
			if ((Object)(object)ownerRoot == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)ownerRoot).GetInstanceID();
			PendingDeathRootIds.Remove(instanceID);
			for (int num = PendingDeaths.Count - 1; num >= 0; num--)
			{
				if (PendingDeaths[num].RootId == instanceID)
				{
					PendingDeaths.RemoveAt(num);
				}
			}
		}

		private static Transform ResolveBarrelRollerOwnerRoot(Transform explosionTransform)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)explosionTransform == (Object)null)
			{
				return null;
			}
			TeamHolder val = ((Component)explosionTransform).GetComponent<TeamHolder>() ?? ((Component)explosionTransform).GetComponentInParent<TeamHolder>();
			if ((Object)(object)val?.spawner != (Object)null)
			{
				Transform root = val.spawner.transform.root;
				if (IsBarrelRollerRoot(root))
				{
					return root;
				}
			}
			if (ContainsBarrelExplosionName(((Object)((Component)explosionTransform).gameObject).name) || ContainsBarrelExplosionName(((Object)explosionTransform.root).name))
			{
				Transform val2 = FindBarrelRollerRootNear(explosionTransform.position);
				if ((Object)(object)val2 != (Object)null)
				{
					return val2;
				}
			}
			Transform root2 = explosionTransform.root;
			if (IsSpawnedBarrelExplosionPrefabRoot(root2))
			{
				return null;
			}
			if (IsBarrelRollerRoot(root2))
			{
				return root2;
			}
			return null;
		}

		private static bool IsSpawnedBarrelExplosionPrefabRoot(Transform root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			if ((Object)(object)((Component)root).GetComponentInChildren<Unit>(true) != (Object)null)
			{
				return false;
			}
			return ContainsBarrelExplosionName(((Object)root).name);
		}

		private static Transform FindBarrelRollerRootNear(Vector3 position)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			Transform result = null;
			float num = 400f;
			foreach (KeyValuePair<int, Transform> activeBarrelRollerRoot in ActiveBarrelRollerRoots)
			{
				Transform value = activeBarrelRollerRoot.Value;
				if (!((Object)(object)value == (Object)null) && !IsSpawnedBarrelExplosionPrefabRoot(value))
				{
					Vector3 val = value.position - position;
					float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
					if (!(sqrMagnitude > num))
					{
						num = sqrMagnitude;
						result = value;
					}
				}
			}
			return result;
		}

		private static void RememberBarrelRollerRoot(Transform root)
		{
			if (!((Object)(object)root == (Object)null))
			{
				ActiveBarrelRollerRoots[((Object)root).GetInstanceID()] = root;
			}
		}

		private static bool IsBarrelRollerOwnedExplosion(Explosion explosion, Transform ownerRoot)
		{
			if ((Object)(object)explosion == (Object)null || (Object)(object)ownerRoot == (Object)null)
			{
				return false;
			}
			if (ContainsBarrelExplosionName(((Object)((Component)explosion).gameObject).name) || ContainsBarrelExplosionName(((Object)((Component)explosion).transform.root).name))
			{
				return true;
			}
			if (!BelongsToRoot(((Component)explosion).transform, ownerRoot))
			{
				return false;
			}
			if (IsRollingBarrelGearTransform(((Component)explosion).transform))
			{
				return true;
			}
			return IsUnderBarrelRollerAbilityMount(((Component)explosion).transform, ownerRoot);
		}

		private static bool ContainsBarrelExplosionName(string objectName)
		{
			if (string.IsNullOrEmpty(objectName))
			{
				return false;
			}
			if (objectName.IndexOf("ExplosionBombBarrel", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			if (objectName.IndexOf("BarrelE_Explosion", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			if (objectName.IndexOf("Barrel", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return objectName.IndexOf("Explosion", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		internal static bool IsBarrelRollerRoot(Transform root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			if (IsSpawnedBarrelExplosionPrefabRoot(root))
			{
				return false;
			}
			int instanceID = ((Object)root).GetInstanceID();
			if (IsCachedBarrelRollerRoot(root, instanceID))
			{
				return true;
			}
			if (NotBarrelRollerRootIds.Contains(instanceID))
			{
				return false;
			}
			Unit component = ((Component)root).GetComponent<Unit>();
			if (!IsBarrelAbilityUnit(root, component))
			{
				NotBarrelRollerRootIds.Add(instanceID);
				return false;
			}
			KnownBarrelRollerRootIds.Add(instanceID);
			RememberBarrelRollerRoot(root);
			return true;
		}

		private static bool ShouldSkipDeathForAbilityKill(Transform root)
		{
			if ((Object)(object)root == (Object)null || !IsBarrelRollerRoot(root))
			{
				return false;
			}
			if (TryGetRecentBarrelExplosionAge(root, out var ageSeconds))
			{
				return ageSeconds <= 0.5f;
			}
			return false;
		}

		private static bool TryGetRecentBarrelExplosionAge(Transform root, out float ageSeconds)
		{
			ageSeconds = float.MaxValue;
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			if (!RecentBarrelExplosionTimeByRoot.TryGetValue(((Object)root).GetInstanceID(), out var value))
			{
				return false;
			}
			ageSeconds = Time.time - value;
			return ageSeconds <= 2.5f;
		}

		internal static bool ShouldSuppressDeathExplosion(Transform root)
		{
			if ((Object)(object)root == (Object)null || !IsBarrelRollerRoot(root))
			{
				return false;
			}
			return HasRecentBarrelExplosion(root);
		}

		internal static void EnsureScheduledFromDead(DataHandler data)
		{
			if (!((Object)(object)data == (Object)null) && data.Dead)
			{
				TryScheduleFromScope(((Component)data).transform, "DataHandler.Dead");
			}
		}

		private static void TryScheduleFromScope(Transform scope, string source)
		{
			if ((Object)(object)scope == (Object)null)
			{
				return;
			}
			Transform root = scope.root;
			if (!IsBarrelRollerRoot(root))
			{
				return;
			}
			if (!TryBuildPlan(root, out var plan))
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("Barrel death plan failed (" + source + ") on " + ((Object)root).name));
				}
			}
			else
			{
				TrySchedule(plan, source);
			}
		}

		private static void TrySchedule(BarrelDeathPlan plan, string source)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: 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_0090: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)plan?.Root == (Object)null || (Object)(object)_runner == (Object)null)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)("Barrel death skip schedule (" + source + "): runner or root missing"));
				}
				return;
			}
			int instanceID = ((Object)plan.Root).GetInstanceID();
			if (!ShouldSkipDeathForAbilityKill(plan.Root) && PendingDeathRootIds.Add(instanceID))
			{
				Vector3 position;
				bool flag = TryResolveExplosionPosition(plan, out position);
				if (!flag && plan.HasSnapshotPosition && IsFinite(plan.SnapshotPosition))
				{
					position = plan.SnapshotPosition;
					flag = true;
				}
				PendingDeaths.Add(new PendingBarrelDeath
				{
					RootId = instanceID,
					Plan = plan,
					ExplodeAt = Time.time + plan.DelaySeconds,
					ExplodePosition = position,
					HasExplodePosition = flag
				});
				if (_queueRunner == null)
				{
					_queueRunner = _runner.StartCoroutine(ProcessDeathQueue());
				}
			}
		}

		[IteratorStateMachine(typeof(<ProcessDeathQueue>d__46))]
		private static IEnumerator ProcessDeathQueue()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ProcessDeathQueue>d__46(0);
		}

		private static void ExecuteDeathExplosion(int rootId, BarrelDeathPlan plan, Vector3 scheduledPosition, bool hasScheduledPosition)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			Transform val = plan?.Root;
			if ((Object)(object)val != (Object)null && ShouldSuppressDeathExplosion(val))
			{
				CancelPendingDeathExplosion(val);
				return;
			}
			if (!TryResolveDeathExplosionPosition(plan, scheduledPosition, hasScheduledPosition, out var position))
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)$"Barrel death execute failed: no position (rootId={rootId})");
				}
				return;
			}
			HideBarrelGear(plan);
			RefreshOwnerUnit(plan);
			_executingDeathExplosion = true;
			try
			{
				TriggerSingleBarrelExplosion(plan, position);
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = _log;
				if (log2 != null)
				{
					log2.LogError((object)$"Barrel death execute failed (rootId={rootId}): {ex.Message}");
				}
			}
			finally
			{
				_executingDeathExplosion = false;
			}
		}

		private static bool TryResolveDeathExplosionPosition(BarrelDeathPlan plan, Vector3 scheduledPosition, bool hasScheduledPosition, out Vector3 position)
		{
			//IL_0001: 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_0042: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector3);
			if (plan == null)
			{
				return false;
			}
			if ((Object)(object)plan.Root != (Object)null && TryResolveExplosionPosition(plan, out position))
			{
				return true;
			}
			if (hasScheduledPosition && IsFinite(scheduledPosition))
			{
				position = scheduledPosition;
				return true;
			}
			if (plan.HasSnapshotPosition && IsFinite(plan.SnapshotPosition))
			{
				position = plan.SnapshotPosition;
				return true;
			}
			return false;
		}

		private static bool TryBuildPlan(Transform root, out BarrelDeathPlan plan)
		{
			//IL_00fb: 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)
			plan = null;
			if ((Object)(object)root == (Object)null || !IsBarrelRollerRoot(root))
			{
				return false;
			}
			float delayFromConditionalEvents = GetDelayFromConditionalEvents(((Component)root).GetComponentsInChildren<ConditionalEvent>(true));
			Holdable[] componentsInChildren = ((Component)root).GetComponentsInChildren<Holdable>(true);
			CollectBarrelHoldableData(root, componentsInChildren, out var barrelRigidbodies, out var barrelAnchors, out var barrelVisuals);
			PickExplosionAssets(((Component)root).GetComponentsInChildren<Explosion>(true), out var cachedExplosion, out var fallbackTemplate);
			GameObject val = FindExplosionPrefab(root);
			if ((Object)(object)val == (Object)null && (Object)(object)cachedExplosion != (Object)null)
			{
				val = FindExplosionPrefabFromTemplate(cachedExplosion);
			}
			if ((Object)(object)val != (Object)null)
			{
				RememberSharedDeathExplosionAssets(val, cachedExplosion ?? fallbackTemplate);
			}
			else if ((Object)(object)_sharedBarrelDeathExplosionPrefab != (Object)null)
			{
				val = _sharedBarrelDeathExplosionPrefab;
			}
			if ((Object)(object)cachedExplosion == (Object)null && (Object)(object)fallbackTemplate == (Object)null && (Object)(object)_sharedBarrelDeathExplosionTemplate != (Object)null)
			{
				fallbackTemplate = _sharedBarrelDeathExplosionTemplate;
			}
			Vector3 position;
			bool hasSnapshotPosition = TryCaptureBarrelSnapshot(barrelRigidbodies, barrelAnchors, root, out position);
			plan = new BarrelDeathPlan
			{
				Root = root,
				DelaySeconds = delayFromConditionalEvents,
				BarrelVisuals = barrelVisuals,
				BarrelRigidbodies = barrelRigidbodies,
				BarrelAnchors = barrelAnchors,
				SnapshotPosition = position,
				HasSnapshotPosition = hasSnapshotPosition,
				CachedBarrelExplosion = cachedExplosion,
				CachedExplosionPrefab = val,
				FallbackExplosionTemplate = (cachedExplosion ?? fallbackTemplate),
				OwnerUnit = ((Component)root).GetComponent<Unit>()
			};
			return true;
		}

		private static float GetDelayFromConditionalEvents(ConditionalEvent[] conditionalEvents)
		{
			float num = 0.45f;
			if (conditionalEvents == null)
			{
				return num;
			}
			for (int i = 0; i < conditionalEvents.Length; i++)
			{
				ConditionalEventInstance[] array = conditionalEvents[i]?.events;
				if (array == null)
				{
					continue;
				}
				foreach (ConditionalEventInstance val in array)
				{
					if (HasUnitDeathCondition(val))
					{
						float delay = val.delay;
						if (delay > num)
						{
							num = delay;
						}
					}
				}
			}
			return num;
		}

		private static void CollectBarrelHoldableData(Transform root, Holdable[] holdables, out Rigidbody[] barrelRigidbodies, out Transform[] barrelAnchors, out GameObject[] barrelVisuals)
		{
			List<Rigidbody> list = new List<Rigidbody>();
			List<Transform> list2 = new List<Transform>();
			List<GameObject> list3 = new List<GameObject>();
			HashSet<int> hashSet = new HashSet<int>();
			HashSet<int> hashSet2 = new HashSet<int>();
			HashSet<int> hashSet3 = new HashSet<int>();
			if (holdables != null)
			{
				foreach (Holdable holdable in holdables)
				{
					if (IsBarrelHoldable(holdable))
					{
						AddBarrelHoldable(holdable, list, list2, list3, hashSet, hashSet2, hashSet3);
					}
				}
			}
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (((Object)val).name.IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					if (hashSet2.Add(((Object)val).GetInstanceID()))
					{
						list2.Add(val);
					}
					if (hashSet3.Add(((Object)((Component)val).gameObject).GetInstanceID()))
					{
						list3.Add(((Component)val).gameObject);
					}
					Rigidbody componentInChildren = ((Component)val).GetComponentInChildren<Rigidbody>();
					if ((Object)(object)componentInChildren != (Object)null && hashSet.Add(((Object)componentInChildren).GetInstanceID()))
					{
						list.Add(componentInChildren);
					}
				}
			}
			barrelRigidbodies = list.ToArray();
			barrelAnchors = list2.ToArray();
			barrelVisuals = list3.ToArray();
		}

		private static void AddBarrelHoldable(Holdable holdable, List<Rigidbody> rigidbodies, List<Transform> anchors, List<GameObject> visuals, HashSet<int> seenBodies, HashSet<int> seenAnchors, HashSet<int> seenVisuals)
		{
			Transform val = (((Object)(object)holdable.rig != (Object)null) ? ((Component)holdable.rig).transform : ((Component)holdable).transform);
			if ((Object)(object)val != (Object)null && seenAnchors.Add(((Object)val).GetInstanceID()))
			{
				anchors.Add(val);
			}
			Rigidbody val2 = holdable.rig ?? ((Component)holdable).GetComponentInChildren<Rigidbody>();
			if ((Object)(object)val2 != (Object)null && seenBodies.Add(((Object)val2).GetInstanceID()))
			{
				rigidbodies.Add(val2);
			}
			if (seenVisuals.Add(((Object)((Component)holdable).gameObject).GetInstanceID()))
			{
				visuals.Add(((Component)holdable).gameObject);
			}
		}

		private static void PickExplosionAssets(Explosion[] explosions, out Explosion cachedExplosion, out Explosion fallbackTemplate)
		{
			cachedExplosion = null;
			fallbackTemplate = null;
			float num = float.MinValue;
			if (explosions == null)
			{
				return;
			}
			foreach (Explosion val in explosions)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				if (fallbackTemplate == null)
				{
					fallbackTemplate = val;
				}
				if (IsBarrelDeathExplosionSource(((Component)val).transform, ((Component)val).transform.root))
				{
					float num2 = ScoreBarrelExplosion(val);
					if (!(num2 <= num))
					{
						num = num2;
						cachedExplosion = val;
					}
				}
			}
		}

		private static GameObject FindExplosionPrefab(Transform root)
		{
			GameObject preferred = null;
			GameObject val = null;
			GameObject any = null;
			RemoveAfterSeconds[] componentsInChildren = ((Component)root).GetComponentsInChildren<RemoveAfterSeconds>(true);
			foreach (RemoveAfterSeconds val2 in componentsInChildren)
			{
				GameObject val3 = val2?.objectToSpawn;
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				if (any == null)
				{
					any = val3;
				}
				if (val2.spawnObjectOnMainRig)
				{
					if (val == null)
					{
						val = val3;
					}
				}
				else
				{
					preferred = val3;
				}
			}
			if ((Object)(object)preferred != (Object)null)
			{
				return preferred;
			}
			KillAfterSeconds[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<KillAfterSeconds>(true);
			foreach (KillAfterSeconds val4 in componentsInChildren2)
			{
				GameObject val5 = val4?.objectToSpawn;
				if (!((Object)(object)val5 == (Object)null))
				{
					if (any == null)
					{
						any = val5;
					}
					if (!val4.spawnObjectOnMainRig)
					{
						return val5;
					}
					if (val == null)
					{
						val = val5;
					}
				}
			}
			CollectSpawnPrefabs(root, ref preferred, ref any);
			return preferred ?? val ?? any;
		}

		private static void CollectSpawnPrefabs(Transform root, ref GameObject preferred, ref GameObject any)
		{
			SpawnObject[] componentsInChildren = ((Component)root).GetComponentsInChildren<SpawnObject>(true);
			foreach (SpawnObject val in componentsInChildren)
			{
				GameObject objectToSpawn = val.objectToSpawn;
				if (!((Object)(object)objectToSpawn == (Object)null))
				{
					if (any == null)
					{
						any = objectToSpawn;
					}
					if (IsRollingBarrelGearTransform(((Component)val).transform))
					{
						preferred = objectToSpawn;
					}
				}
			}
			CollisionEvent[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<CollisionEvent>(true);
			foreach (CollisionEvent val2 in componentsInChildren2)
			{
				GameObject objectToSpawn2 = val2.objectToSpawn;
				if (!((Object)(object)objectToSpawn2 == (Object)null))
				{
					if (any == null)
					{
						any = objectToSpawn2;
					}
					if (IsRollingBarrelGearTransform(((Component)val2).transform))
					{
						preferred = objectToSpawn2;
					}
				}
			}
		}

		internal static bool IsBarrelDeathDelayEvent(Component component)
		{
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			ConditionalEvent componentInParent = component.GetComponentInParent<ConditionalEvent>();
			if (componentInParent?.events == null)
			{
				return IsRollingBarrelGearTransform(component.transform);
			}
			for (int i = 0; i < componentInParent.events.Length; i++)
			{
				if (HasUnitDeathCondition(componentInParent.events[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static GameObject FindExplosionPrefabFromTemplate(Explosion template)
		{
			if ((Object)(object)template == (Object)null)
			{
				return null;
			}
			Transform val = ((Component)template).transform;
			while ((Object)(object)val != (Object)null)
			{
				RemoveAfterSeconds component = ((Component)val).GetComponent<RemoveAfterSeconds>();
				if ((Object)(object)component?.objectToSpawn != (Object)null)
				{
					return component.objectToSpawn;
				}
				val = val.parent;
			}
			return null;
		}

		private static bool IsBarrelAbilityMountTransform(Transform transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return false;
			}
			string name = ((Object)transform).name;
			if (name.IndexOf("Wings_Leg_Barrel", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			if (name.IndexOf("Leg_Barrel", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			return name.IndexOf("BarrelRoller", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static bool IsBarrelRollerAbilityTransform(Transform transform)
		{
			return IsBarrelAbilityMountTransform(transform);
		}

		private static bool IsUnderBarrelAbilityMount(Transform transform, Transform ownerRoot)
		{
			Transform val = transform;
			while ((Object)(object)val != (Object)null && (!((Object)(object)ownerRoot != (Object)null) || !((Object)(object)val == (Object)(object)ownerRoot)))
			{
				if (IsBarrelAbilityMountTransform(val))
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static bool IsUnderBarrelRollerAbilityMount(Transform transform, Transform ownerRoot)
		{
			return IsUnderBarrelAbilityMount(transform, ownerRoot);
		}

		private static bool IsBarrelAbilityUnit(Transform root, Unit unit)
		{
			if (MatchesBarrelRollerBlueprint(unit))
			{
				return true;
			}
			return HasBarrelAbilityGear(root);
		}

		private static bool HasBarrelAbilityGear(Transform root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (IsBarrelAbilityMountTransform(componentsInChildren[i]))
				{
					return true;
				}
			}
			Holdable[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<Holdable>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				if (IsBarrelHoldable(componentsInChildren2[i]))
				{
					return true;
				}
			}
			Explosion[] componentsInChildren3 = ((Component)root).GetComponentsInChildren<Explosion>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				if (IsBarrelDeathExplosionSource(((Component)componentsInChildren3[i]).transform, root))
				{
					return true;
				}
			}
			DelayEvent[] componentsInChildren4 = ((Component)root).GetComponentsInChildren<DelayEvent>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				if (IsBarrelDeathDelayEvent((Component)(object)componentsInChildren4[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsBarrelDeathExplosionSource(Transform transform, Transform root)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return false;
			}
			if (ContainsBarrelExplosionName(((Object)((Component)transform).gameObject).name))
			{
				return true;
			}
			if (IsRollingBarrelGearTransform(transform))
			{
				return true;
			}
			return IsUnderBarrelAbilityMount(transform, root);
		}

		private static bool MatchesBarrelRollerBlueprint(Unit unit)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			object obj;
			if (unit == null)
			{
				obj = null;
			}
			else
			{
				UnitBlueprint unitBlueprint = unit.unitBlueprint;
				obj = ((unitBlueprint != null) ? unitBlueprint.Entity : null);
			}
			if (obj == null)
			{
				return false;
			}
			if (unit.unitBlueprint.Entity.GUID.m_ID == 846602731)
			{
				return true;
			}
			string name = unit.unitBlueprint.Entity.Name;
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			if (name.IndexOf("BOXER", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return false;
			}
			if (name.IndexOf("BARRELROLLER", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			if (name.IndexOf("Barrel", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return name.IndexOf("Roller", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static bool HasUnitDeathCondition(ConditionalEventInstance instance)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			EventCondition[] array = instance?.conditions;
			if (array == null)
			{
				return false;
			}
			foreach (EventCondition obj in array)
			{
				if (obj != null && (int)obj.conditionType == 5)
				{
					return true;
				}
			}
			return false;
		}

		private static bool TryResolveExplosionPosition(BarrelDeathPlan plan, out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector3);
			if ((Object)(object)plan?.Root == (Object)null)
			{
				return false;
			}
			if (TryGetTrackedRigidbodyPosition(plan.BarrelRigidbodies, plan.Root, out position))
			{
				return true;
			}
			if (TryGetLiveScanPosition(plan.Root, plan.BarrelVisuals, out position))
			{
				return true;
			}
			if (TryGetAnchorPosition(plan.BarrelAnchors, plan.Root, out position))
			{
				return true;
			}
			if (plan.HasSnapshotPosition && IsUsableExplosionPosition(plan.Root, plan.SnapshotPosition))
			{
				position = plan.SnapshotPosition;
				return true;
			}
			DataHandler componentInChildren = ((Component)plan.Root).GetComponentInChildren<DataHandler>();
			if ((Object)(object)componentInChildren?.mainRig != (Object)null && IsUsableExplosionPosition(plan.Root, componentInChildren.mainRig.position))
			{
				position = componentInChildren.mainRig.position;
				return true;
			}
			if (IsUsableExplosionPosition(plan.Root, plan.Root.position))
			{
				position = plan.Root.position;
				return true;
			}
			return false;
		}

		private static bool TryCaptureBarrelSnapshot(Rigidbody[] barrelRigidbodies, Transform[] barrelAnchors, Transform root, out Vector3 position)
		{
			if (TryGetTrackedRigidbodyPosition(barrelRigidbodies, root, out position))
			{
				return true;
			}
			return TryGetAnchorPosition(barrelAnchors, root, out position);
		}

		private static bool TryGetAnchorPosition(Transform[] anchors, Transform root, out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_002b: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector3);
			if (anchors == null)
			{
				return false;
			}
			foreach (Transform val in anchors)
			{
				if (!((Object)(object)val == (Object)null))
				{
					position = GetTransformCenter(val);
					if (IsUsableExplosionPosition(root, position))
					{
						return true;
					}
				}
			}
			position = default(Vector3);
			return false;
		}

		private static bool TryGetTrackedRigidbodyPosition(Rigidbody[] trackedRigidbodies, Transform root, out Vector3 position)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector3);
			Rigidbody val = null;
			float num = float.MinValue;
			if (trackedRigidbodies != null)
			{
				foreach (Rigidbody val2 in trackedRigidbodies)
				{
					if (IsAliveRigidbody(val2))
					{
						float num2 = ScoreBarrelRigidbody(val2);
						if (num2 > num)
						{
							num = num2;
							val = val2;
						}
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			position = val.worldCenterOfMass;
			return IsUsableExplosionPosition(root, position);
		}

		private static bool TryGetLiveScanPosition(Transform root, GameObject[] barrelVisuals, out Vector3 position)
		{
			//IL_0001: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			position = default(Vector3);
			Rigidbody val = FindBarrelRigidbody(root, null);
			if ((Object)(object)val != (Object)null)
			{
				position = val.worldCenterOfMass;
				return IsUsableExplosionPosition(root, position);
			}
			Holdable[] componentsInChildren = ((Component)root).GetComponentsInChildren<Holdable>(true);
			foreach (Holdable val2 in componentsInChildren)
			{
				if (!IsBarrelHoldable(val2))
				{
					continue;
				}
				Transform val3 = (((Object)(object)val2.rig != (Object)null) ? ((Component)val2.rig).transform : ((Component)val2).transform);
				if (!((Object)(object)val3 == (Object)null))
				{
					position = GetTransformCenter(val3);
					if (IsUsableExplosionPosition(root, position))
					{
						return true;
					}
				}
			}
			Transform[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val4 in componentsInChildren2)
			{
				if (((Object)val4).name.IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					position = GetTransformCenter(val4);
					if (IsUsableExplosionPosition(root, position))
					{
						return true;
					}
				}
			}
			if (barrelVisuals != null)
			{
				foreach (GameObject val5 in barrelVisuals)
				{
					if (!((Object)(object)val5 == (Object)null) && val5.activeInHierarchy)
					{
						position = GetTransformCenter(val5.transform);
						if (IsUsableExplosionPosition(root, position))
						{
							return true;
						}
					}
				}
			}
			position = default(Vector3);
			return false;
		}

		private static bool IsUsableExplosionPosition(Transform root, Vector3 position)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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)
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			if (float.IsNaN(position.x) || float.IsNaN(position.y) || float.IsNaN(position.z))
			{
				return false;
			}
			if (((Vector3)(ref position)).sqrMagnitude < 0.25f)
			{
				return false;
			}
			Vector3 position2 = root.position;
			DataHandler componentInChildren = ((Component)root).GetComponentInChildren<DataHandler>();
			if ((Object)(object)componentInChildren?.mainRig != (Object)null)
			{
				position2 = componentInChildren.mainRig.position;
			}
			Vector3 val = position - position2;
			return ((Vector3)(ref val)).sqrMagnitude <= 6400f;
		}

		private static bool IsAliveRigidbody(Rigidbody rigidbody)
		{
			return (Object)(object)rigidbody != (Object)null;
		}

		private static bool BelongsToRoot(Transform transform, Transform root)
		{
			if ((Object)(object)transform == (Object)null || (Object)(object)root == (Object)null)
			{
				return false;
			}
			return (Object)(object)transform.root == (Object)(object)root;
		}

		private static Rigidbody FindBarrelRigidbody(Transform root, Rigidbody[] trackedRigidbodies)
		{
			Rigidbody result = null;
			float num = float.MinValue;
			if (trackedRigidbodies != null)
			{
				foreach (Rigidbody val in trackedRigidbodies)
				{
					if (IsAliveRigidbody(val))
					{
						float num2 = ScoreBarrelRigidbody(val);
						if (num2 > num)
						{
							num = num2;
							result = val;
						}
					}
				}
			}
			Holdable[] componentsInChildren = ((Component)root).GetComponentsInChildren<Holdable>(true);
			foreach (Holdable val2 in componentsInChildren)
			{
				if (!IsBarrelHoldable(val2))
				{
					continue;
				}
				Rigidbody val3 = val2.rig ?? ((Component)val2).GetComponentInChildren<Rigidbody>();
				if (!((Object)(object)val3 == (Object)null) && BelongsToRoot(((Component)val3).transform, root))
				{
					float num3 = ScoreBarrelRigidbody(val3) + 50f;
					if (num3 > num)
					{
						num = num3;
						result = val3;
					}
				}
			}
			Rigidbody[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody val4 in componentsInChildren2)
			{
				if (BelongsToRoot(((Component)val4).transform, root) && IsRollingBarrelGearTransform(((Component)val4).transform))
				{
					float num4 = ScoreBarrelRigidbody(val4);
					if (num4 > num)
					{
						num = num4;
						result = val4;
					}
				}
			}
			return result;
		}

		private static bool IsBarrelHoldable(Holdable holdable)
		{
			if ((Object)(object)holdable == (Object)null)
			{
				return false;
			}
			if (IsAbilityMountName(((Object)holdable).name))
			{
				return false;
			}
			if (IsBarrelName(((Object)holdable).name))
			{
				return true;
			}
			return IsRollingBarrelGearTransform(((Component)holdable).transform);
		}

		private static bool IsAbilityMountName(string objectName)
		{
			if (string.IsNullOrEmpty(objectName))
			{
				return false;
			}
			if (objectName.IndexOf("BarrelRoller", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return objectName.IndexOf("Wings_Leg_Barrel", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		internal static bool IsRollingBarrelGearTransform(Transform transform)
		{
			Transform val = transform;
			while ((Object)(object)val != (Object)null)
			{
				if (IsAbilityMountName(((Object)val).name))
				{
					return false;
				}
				if (((Object)val).name.IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
				if (IsBarrelName(((Object)val).name))
				{
					return true;
				}
				if ((Object)(object)val.parent == (Object)null)
				{
					break;
				}
				val = val.parent;
			}
			return false;
		}

		private static float ScoreBarrelRigidbody(Rigidbody rigidbody)
		{
			float num = rigidbody.mass;
			string name = ((Object)((Component)rigidbody).transform).name;
			if (name.IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				num += 200f;
			}
			if (IsBarrelName(name))
			{
				num += 100f;
			}
			return num;
		}

		private static Vector3 GetTransformCenter(Transform transform)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_002d: 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)
			if ((Object)(object)transform == (Object)null)
			{
				return Vector3.zero;
			}
			Renderer[] componentsInChildren = ((Component)transform).GetComponentsInChildren<Renderer>(true);
			if (componentsInChildren.Length != 0)
			{
				Bounds bounds = componentsInChildren[0].bounds;
				for (int i = 1; i < componentsInChildren.Length; i++)
				{
					((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds);
				}
				return ((Bounds)(ref bounds)).center;
			}
			Rigidbody componentInChildren = ((Component)transform).GetComponentInChildren<Rigidbody>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				return componentInChildren.worldCenterOfMass;
			}
			return transform.position;
		}

		private static bool IsBarrelName(string objectName)
		{
			if (string.IsNullOrEmpty(objectName))
			{
				return false;
			}
			if (objectName.IndexOf("Barrel", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return false;
			}
			if (objectName.IndexOf("DoubleBarrel", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return false;
			}
			if (objectName.IndexOf("GunBarrel", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return false;
			}
			return true;
		}

		private static Unit RefreshOwnerUnit(BarrelDeathPlan plan)
		{
			if (plan == null)
			{
				return null;
			}
			if ((Object)(object)plan.OwnerUnit != (Object)null)
			{
				return plan.OwnerUnit;
			}
			if ((Object)(object)plan.Root == (Object)null)
			{
				return null;
			}
			plan.OwnerUnit = ((Component)plan.Root).GetComponent<Unit>();
			return plan.OwnerUnit;
		}

		private static void RememberSharedDeathExplosionAssets(GameObject prefab, Explosion template)
		{
			if ((Object)(object)prefab != (Object)null && (Object)(object)_sharedBarrelDeathExplosionPrefab == (Object)null)
			{
				_sharedBarrelDeathExplosionPrefab = prefab;
			}
			if ((Object)(object)template != (Object)null && (Object)(object)_sharedBarrelDeathExplosionTemplate == (Object)null)
			{
				_sharedBarrelDeathExplosionTemplate = template;
			}
		}

		private static void TriggerSingleBarrelExplosion(BarrelDeathPlan plan, Vector3 position)
		{
			//IL_0000: 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_003f: 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_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: 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)
			if (!IsFinite(position))
			{
				return;
			}
			Unit ownerUnit = RefreshOwnerUnit(plan);
			Explosion template = plan.FallbackExplosionTemplate ?? plan.CachedBarrelExplosion ?? _sharedBarrelDeathExplosionTemplate;
			if ((Object)(object)plan.CachedExplosionPrefab != (Object)null)
			{
				GameObject obj = Object.Instantiate<GameObject>(plan.CachedExplosionPrefab, position, Quaternion.identity);
				PrepareDeathExplosionObject(obj, template);
				FinalizeDeathExplosionInstance(obj, ownerUnit);
				obj.SetActive(true);
				TriggerExplosionOnObject(obj, template);
			}
			else if ((Object)(object)_sharedBarrelDeathExplosionPrefab != (Object)null)
			{
				GameObject obj2 = Object.Instantiate<GameObject>(_sharedBarrelDeathExplosionPrefab, position, Quaternion.identity);
				PrepareDeathExplosionObject(obj2, template);
				FinalizeDeathExplosionInstance(obj2, ownerUnit);
				obj2.SetActive(true);
				TriggerExplosionOnObject(obj2, template);
			}
			else if ((Object)(object)plan.CachedBarrelExplosion != (Object)null)
			{
				GameObject obj3 = Object.Instantiate<GameObject>(((Component)plan.CachedBarrelExplosion).gameObject, position, ((Component)plan.CachedBarrelExplosion).transform.rotation);
				PrepareDeathExplosionObject(obj3, template);
				FinalizeDeathExplosionInstance(obj3, ownerUnit);
				obj3.SetActive(true);
				TriggerExplosionOnObject(obj3, template);
				Object.Destroy((Object)(object)obj3, 12f);
			}
			else if (!TryCreateFallbackExplosion(position, template, ownerUnit))
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogWarning((object)"Barrel death fallback explode failed: no viable explosion path");
				}
			}
		}

		private static void AttachTeamHolder(GameObject instance, Unit ownerUnit)
		{
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)ownerUnit == (Object)null))
			{
				TeamHolder.AddTeamHolder(instance, ownerUnit, (TeamHolder)null);
			}
		}

		private static void FinalizeDeathExplosionInstance(GameObject instance, Unit ownerUnit)
		{
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)ownerUnit == (Object)null))
			{
				AttachTeamHolder(instance, ownerUnit);
				ApplyOwnerLevel(instance, ownerUnit);
			}
		}

		private static void StripDeathExplosionStatusEffects(GameObject instance)
		{
			if (!((Object)(object)instance == (Object)null))
			{
				Explosion[] componentsInChildren = instance.GetComponentsInChildren<Explosion>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].addEffectFromParent = false;
				}
				ExplosionEffect[] componentsInChildren2 = instance.GetComponentsInChildren<ExplosionEffect>(true);
				for (int i = 0; i < componentsInChildren2.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren2[i]);
				}
				AddTargetableEffect[] componentsInChildren3 = instance.GetComponentsInChildren<AddTargetableEffect>(true);
				for (int i = 0; i < componentsInChildren3.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren3[i]);
				}
			}
		}

		private static void ApplyOwnerLevel(GameObject instance, Unit ownerUnit)
		{
			Level val = FindOwnerLevel(ownerUnit);
			if (!((Object)(object)val == (Object)null))
			{
				Level obj = instance.GetComponent<Level>() ?? instance.AddComponent<Level>();
				obj.levelMultiplier = val.levelMultiplier;
				obj.level = val.level;
				obj.ignoreTeam = val.ignoreTeam;
				TargetableEffect[] componentsInChildren = instance.GetComponentsInChildren<TargetableEffect>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].damageMultiplier = val.levelMultiplier;
				}
			}
		}

		private static Level FindOwnerLevel(Unit ownerUnit)
		{
			if ((Object)(object)ownerUnit == (Object)null)
			{
				return null;
			}
			Level component = ((Component)ownerUnit).GetComponent<Level>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			return ((Component)ownerUnit).GetComponentInChildren<Level>(true);
		}

		private static void HideBarrelGear(BarrelDeathPlan plan)
		{
			if (plan != null)
			{
				HideBarrelGearLive(plan.Root, plan.BarrelVisuals, plan.BarrelRigidbodies);
			}
		}

		private static void HideBarrelGearLive(Transform root, GameObject[] cachedVisuals, Rigidbody[] cachedRigidbodies)
		{
			if (cachedVisuals != null)
			{
				for (int i = 0; i < cachedVisuals.Length; i++)
				{
					HideGameObjectTree(cachedVisuals[i]);
				}
			}
			if (cachedRigidbodies != null)
			{
				for (int j = 0; j < cachedRigidbodies.Length; j++)
				{
					HideRigidbodyGear(cachedRigidbodies[j]);
				}
			}
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			Holdable[] componentsInChildren = ((Component)root).GetComponentsInChildren<Holdable>(true);
			foreach (Holdable val in componentsInChildren)
			{
				if (IsBarrelHoldable(val))
				{
					HideGameObjectTree(((Component)val).gameObject);
					if ((Object)(object)val.rig != (Object)null)
					{
						HideRigidbodyGear(val.rig);
					}
				}
			}
			Transform[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<Transform>(true);
			foreach (Transform val2 in componentsInChildren2)
			{
				if (IsRollingBarrelGearTransform(val2) || ((Object)val2).name.IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					HideGameObjectTree(((Component)val2).gameObject);
				}
			}
		}

		private static void HideRigidbodyGear(Rigidbody rigidbody)
		{
			if (!((Object)(object)rigidbody == (Object)null))
			{
				HideGameObjectTree(((Component)rigidbody).gameObject);
			}
		}

		private static void HideGameObjectTree(GameObject target)
		{
			if ((Object)(object)target == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren = target.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = false;
				}
			}
			Collider[] componentsInChildren2 = target.GetComponentsInChildren<Collider>(true);
			foreach (Collider val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null)
				{
					val2.enabled = false;
				}
			}
			target.SetActive(false);
		}

		private static bool HasRecentBarrelExplosion(Transform root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			if (!RecentBarrelExplosionTimeByRoot.TryGetValue(((Object)root).GetInstanceID(), out var value))
			{
				return false;
			}
			return Time.time - value <= 2.5f;
		}

		private static float ScoreBarrelExplosion(Explosion explosion)
		{
			float num = (((Object)(object)explosion != (Object)null) ? (explosion.radius + explosion.damage * 0.01f) : 0f);
			if ((((explosion != null) ? ((Object)((Component)explosion).transform).name : null) ?? string.Empty).IndexOf("BarrelArmor", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				num += 100f;
			}
			return num;
		}

		private static void PrepareDeathExplosionObject(GameObject instance, Explosion template)
		{
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			instance.SetActive(false);
			StripDeathExplosionStatusEffects(instance);
			Explosion[] componentsInChildren = instance.GetComponentsInChildren<Explosion>(true);
			foreach (Explosion val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.automatic = false;
					ApplyDeathExplosionStats(val, template);
				}
			}
		}

		private static bool TryCreateFallbackExplosion(Vector3 position, Explosion template, Unit ownerUnit)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!IsFinite(position) || ((Vector3)(ref position)).sqrMagnitude < 0.25f)
			{
				return false;
			}
			GameObject val = new GameObject("StayCombatFix_BarrelExplosion");
			try
			{
				val.transform.position = position;
				FinalizeDeathExplosionInstance(val, ownerUnit);
				Explosion obj = val.AddComponent<Explosion>();
				ApplyDeathExplosionStats(obj, template);
				obj.automatic = false;
				obj.Explode();
				Object.Destroy((Object)(object)val, 10f);
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogError((object)("Barrel death fallback explode failed: " + ex.Message));
				}
				Object.Destroy((Object)(object)val);
				return false;
			}
		}

		private static bool IsFinite(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 (!float.IsNaN(value.x) && !float.IsNaN(value.y))
			{
				return !float.IsNaN(value.z);
			}
			return false;
		}

		private static void TriggerExplosionOnObject(GameObject instance, Explosion template)
		{
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Explosion[] componentsInChildren = instance.GetComponentsInChildren<Explosion>(true);
			Explosion val = null;
			float num = float.MinValue;
			foreach (Explosion val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					float num2 = val2.radius + val2.damage * 0.01f;
					if (!(num2 <= num))
					{
						num = num2;
						val = val2;
					}
				}
			}
			if (!((Object)(object)val == (Object)null))
			{
				ApplyDeathExplosionStats(val, template);
				val.automatic = false;
				val.Explode();
			}
		}

		private unsafe static void ApplyDeathExplosionStats(Explosion explosion, Explosion template)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_0099->IL0099: Incompatible stack types: O vs I4
			//IL_0093->IL0099: Incompatible stack types: I4 vs O
			//IL_0093->IL0099: Incompatible stack types: O vs I4
			if (!((Object)(object)explosion == (Object)null))
			{
				float radius = (((Object)(object)template != (Object)null) ? template.radius : 4f);
				float force = (((Object)(object)template != (Object)null) ? template.force : 350f);
				float minMassCap = (((Object)(object)template != (Object)null) ? template.minMassCap : 25f);
				explosion.damage = 15f;
				explosion.percentDamage = 0f;
				explosion.radius = radius;
				explosion.force = force;
				explosion.minMassCap = minMassCap;
				explosion.layerMask = LayerMask.op_Implicit(-1);
				object obj = explosion;
				int num;
				if ((Object)(object)template != (Object)null)
				{
					obj = template.forceDirection;
					num = (int)obj;
				}
				else
				{
					num = 0;
					obj = num;
					num = (int)obj;
				}
				System.Runtime.CompilerServices.Unsafe.Write(&((Explosion)num).forceDirection, (ForceDirection)obj);
				explosion.ignoreTeamMates = (Object)(object)template != (Object)null && template.ignoreTeamMates;
				explosion.ignoreRoot = true;
			}
		}
	}
	internal static class BarrelRollerDeathPatches
	{
		public static bool ConditionalEvent_OnUnitDead_Prefix(ConditionalEvent __instance)
		{
			Transform val = ((__instance != null) ? ((Component)__instance).transform.root : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			return !BarrelRollerDeathLogic.IsBarrelRollerRoot(val);
		}

		public static bool Explosion_Explode_Prefix(Explosion __instance)
		{
			BarrelRollerDeathLogic.PrepareBarrelOwnedExplosionForDetonation(__instance);
			return !BarrelRollerDeathLogic.TryBlockDuplicateBarrelExplosion(__instance);
		}

		public static void KillAfterSeconds_Spawn_Postfix(KillAfterSeconds __instance)
		{
			BarrelRollerDeathLogic.NotifyBarrelAbilityExplosionFromSpawn((__instance != null) ? ((Component)__instance).transform : null, __instance?.objectToSpawn);
		}

		public static void RemoveAfterSeconds_TriggerRemoval_Postfix(MonoBehaviour __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !(((object)__instance).GetType().Name != "RemoveAfterSeconds"))
			{
				GameObject value = Traverse.Create((object)__instance).Field<GameObject>("objectToSpawn").Value;
				BarrelRollerDeathLogic.NotifyBarrelAbilityExplosionFromSpawn(((Component)__instance).transform, value);
			}
		}

		public static bool DelayEvent_Go_Prefix(DelayEvent __instance)
		{
			Transform val = ((__instance != null) ? ((Component)__instance).transform.root : null);
			if ((Object)(object)val == (Object)null || !BarrelRollerDeathLogic.IsBarrelRollerRoot(val))
			{
				return true;
			}
			if (!BarrelRollerDeathLogic.IsBarrelDeathDelayEvent((Component)(object)__instance))
			{
				return true;
			}
			DataHandler componentInChildren = ((Component)val).GetComponentInChildren<DataHandler>();
			if ((Object)(object)componentInChildren == (Object)null || !componentInChildren.Dead)
			{
				return true;
			}
			return false;
		}

		public static void GameStateManager_EnterPlacementState_Postfix()
		{
			BarrelRollerDeathLogic.ResetBattleCaches();
		}
	}
	internal sealed class FactionCreatorCostHoverState : MonoBehaviour
	{
		private bool _captured;

		private Transform _costParent;

		private int _costSiblingIndex;

		private Vector2 _anchorMin;

		private Vector2 _anchorMax;

		private Vector2 _pivot;

		private Vector2 _anchoredPosition;

		private Vector3 _localScale;

		internal void CaptureCostLayout(RectTransform costRect)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			if (!_captured && !((Object)(object)costRect == (Object)null))
			{
				_costParent = ((Transform)costRect).parent;
				_costSiblingIndex = ((Transform)costRect).GetSiblingIndex();
				_anchorMin = costRect.anchorMin;
				_anchorMax = costRect.anchorMax;
				_pivot = costRect.pivot;
				_anchoredPosition = costRect.anchoredPosition;
				_localScale = ((Transform)costRect).localScale;
				_captured = true;
			}
		}

		internal void RestoreCostLayout(RectTransform costRect)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_005d: Unknown result type (might be due to invalid IL or missing references)
			if (_captured && !((Object)(object)costRect == (Object)null))
			{
				((Transform)costRect).SetParent(_costParent, false);
				((Transform)costRect).SetSiblingIndex(_costSiblingIndex);
				costRect.anchorMin = _anchorMin;
				costRect.anchorMax = _anchorMax;
				costRect.pivot = _pivot;
				costRect.anchoredPosition = _anchoredPosition;
				((Transform)costRect).localScale = _localScale;
			}
		}

		internal static FactionCreatorCostHoverState GetOrCreate(UnitButtonBase button)
		{
			return ((Component)button).gameObject.GetComponent<FactionCreatorCostHoverState>() ?? ((Component)button).gameObject.AddComponent<FactionCreatorCostHoverState>();
		}
	}
	internal sealed class FactionCreatorDragScrollSession : MonoBehaviour
	{
		private ScrollRect _scrollRect;

		private Camera _eventCamera;

		private FactionCreatorUnitDragReorder _drag;

		internal void Begin(ScrollRect scrollRect, Camera eventCamera, FactionCreatorUnitDragReorder drag)
		{
			_scrollRect = scrollRect;
			_eventCamera = eventCamera;
			_drag = drag;
		}

		private void Update()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_scrollRect == (Object)null) && !((Object)(object)_drag == (Object)null))
			{
				FactionCreatorReorderLogic.UpdateDragScroll(_scrollRect, _drag.CurrentScreenPosition, _eventCamera);
			}
		}
	}
	internal static class FactionCreatorDropGap
	{
		private const string GapObjectName = "StayCombatFix_DropGap";

		internal static RectTransform Create(RectTransform listParent, RectTransform unitButton, bool horizontal)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			GameObject val = new GameObject("StayCombatFix_DropGap", new Type[1] { typeof(RectTransform) });
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)listParent, false);
			((Transform)component).localScale = Vector3.one;
			LayoutElement obj = val.AddComponent<LayoutElement>();
			float num = LayoutUtility.GetPreferredWidth(unitButton);
			float num2 = LayoutUtility.GetPreferredHeight(unitButton);
			Rect rect;
			if (num <= 1f)
			{
				rect = unitButton.rect;
				num = ((Rect)(ref rect)).width;
			}
			if (num2 <= 1f)
			{
				rect = unitButton.rect;
				num2 = ((Rect)(ref rect)).height;
			}
			obj.preferredWidth = num;
			obj.preferredHeight = num2;
			obj.minWidth = num;
			obj.minHeight = num2;
			obj.flexibleWidth = 0f;
			obj.flexibleHeight = 0f;
			CreateCircleHighlight(component, unitButton, num, num2);
			return component;
		}

		internal static void Destroy(RectTransform gap)
		{
			if ((Object)(object)gap != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)gap).gameObject);
			}
		}

		private static void CreateCircleHighlight(RectTransform gapRect, RectTransform unitButton, float width, float height)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: 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_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			UnitButtonBase component = ((Component)unitButton).GetComponent<UnitButtonBase>();
			Image val = component?.NameSelect;
			float num = Mathf.Min(width, height);
			GameObject val2 = new GameObject("Highlight", new Type[1] { typeof(RectTransform) });
			RectTransform component2 = val2.GetComponent<RectTransform>();
			((Transform)component2).SetParent((Transform)(object)gapRect, false);
			component2.anchorMin = new Vector2(0.5f, 0.5f);
			component2.anchorMax = new Vector2(0.5f, 0.5f);
			component2.pivot = new Vector2(0.5f, 0.5f);
			component2.sizeDelta = new Vector2(num, num);
			component2.anchoredPosition = Vector2.zero;
			Image val3 = val2.AddComponent<Image>();
			((Graphic)val3).raycastTarget = false;
			val3.preserveAspect = true;
			((Graphic)val3).color = new Color(1f, 1f, 1f, 0.38f);
			if ((Object)(object)val != (Object)null && (Object)(object)val.sprite != (Object)null)
			{
				val3.sprite = val.sprite;
				val3.type = val.type;
			}
			else if ((Object)(object)component?.IconImage != (Object)null && (Object)(object)component.IconImage.sprite != (Object)null)
			{
				val3.sprite = component.IconImage.sprite;
			}
		}
	}
	internal static class FactionCreatorPatches
	{
		public static void AddNewUnit_Postfix(FactionCreatorManager __instance)
		{
			if (!((Object)(object)__instance?.FactionListParent == (Object)null) && __instance.FactionListParent.childCount != 0)
			{
				FactionCreatorReorderLogic.AttachDragHandle(((Component)__instance.FactionListParent.GetChild(__instance.FactionListParent.childCount - 1)).GetComponent<UnitButtonBase>(), __instance);
			}
		}

		public static void LoadFaction_Postfix(FactionCreatorManager __instance)
		{
			FactionCreatorReorderLogic.RefreshAllDragHandles(__instance);
		}

		public static void SaveNewFaction_Prefix(FactionCreatorManager __instance)
		{
			FactionCreatorReorderLogic.SyncAddedUnitsFromHierarchy(__instance);
		}

		public static void GetFactionUnits_Prefix(FactionCreatorManager __instance)
		{
			FactionCreatorReorderLogic.SyncAddedUnitsFromHierarchy(__instance);
		}

		public static bool UnitButtonFactionCreator_OnClick_Prefix(UnitButtonFactionCreator __instance)
		{
			FactionCreatorUnitDragReorder component = ((Component)__instance).GetComponent<FactionCreatorUnitDragReorder>();
			if (!((Object)(object)component == (Object)null))
			{
				return !component.ConsumeClickSuppression();
			}
			return true;
		}

		public static void UnitButtonBase_OnPointerEnter_Postfix(UnitButtonBase __instance)
		{
			FactionCreatorUnitCostHover.ShowOnHover(__instance);
		}

		public static void UnitButtonBase_OnPointerExit_Postfix(UnitButtonBase __instance)
		{
			FactionCreatorUnitCostHover.HideOnHover(__instance);
		}

		public static void UnitButtonBase_OnSelect_Postfix(UnitButtonBase __instance)
		{
			FactionCreatorUnitCostHover.ShowOnHover(__instance);
		}

		public static void UnitButtonBase_OnDeselect_Postfix(UnitButtonBase __instance)
		{
			FactionCreatorUnitCostHover.HideOnHover(__instance);
		}
	}
	internal static class FactionCreatorReorderLogic
	{
		private static readonly FieldInfo AddedUnitsField = AccessTools.Field(typeof(FactionCreatorManager), "addedUnits");

		private static FieldInfo _spawnedButtonField;

		internal static void AttachDragHandle(UnitButtonBase button, FactionCreatorManager manager)
		{
			if (!((Object)(object)button == (Object)null) && !((Object)(object)manager == (Object)null) && !((Object)(object)((Component)button).GetComponent<FactionCreatorUnitDragReorder>() != (Object)null))
			{
				((Component)button).gameObject.AddComponent<FactionCreatorUnitDragReorder>().Initialize(manager, button);
			}
		}

		internal static void RefreshAllDragHandles(FactionCreatorManager manager)
		{
			if ((Object)(object)manager?.FactionListParent == (Object)null)
			{
				return;
			}
			for (int i = 0; i < manager.FactionListParent.childCount; i++)
			{
				UnitButtonBase component = ((Component)manager.FactionListParent.GetChild(i)).GetComponent<UnitButtonBase>();
				if ((Object)(object)component != (Object)null)
				{
					AttachDragHandle(component, manager);
				}
			}
		}

		internal static int GetUnitIndex(FactionCreatorManager manager, UnitButtonBase button)
		{
			IList addedUnits = GetAddedUnits(manager);
			if (addedUnits == null || (Object)(object)button == (Object)null)
			{
				return -1;
			}
			for (int i = 0; i < addedUnits.Count; i++)
			{
				if ((Object)(object)GetSpawnedButton(addedUnits[i]) == (Object)(object)button)
				{
					return i;
				}
			}
			return -1;
		}

		internal static void SyncAddedUnitsFromHierarchy(FactionCreatorManager manager)
		{
			IList addedUnits = GetAddedUnits(manager);
			Transform val = manager?.FactionListParent;
			if (addedUnits == null || (Object)(object)val == (Object)null || addedUnits.Count == 0)
			{
				return;
			}
			Dictionary<UnitButtonBase, object> dictionary = new Dictionary<UnitButtonBase, object>();
			for (int i = 0; i < addedUnits.Count; i++)
			{
				UnitButtonBase spawnedButton = GetSpawnedButton(addedUnits[i]);
				if ((Object)(object)spawnedButton != (Object)null && !dictionary.ContainsKey(spawnedButton))
				{
					dictionary[spawnedButton] = addedUnits[i];
				}
			}
			List<object> list = new List<object>();
			for (int j = 0; j < val.childCount; j++)
			{
				UnitButtonBase component = ((Component)val.GetChild(j)).GetComponent<UnitButtonBase>();
				if ((Object)(object)component != (Object)null && dictionary.TryGetValue(component, out var value))
				{
					list.Add(value);
				}
			}
			if (list.Count == addedUnits.Count)
			{
				addedUnits.Clear();
				for (int k = 0; k < list.Count; k++)
				{
					addedUnits.Add(list[k]);
				}
			}
		}

		internal static ScrollRect FindListScrollRect(FactionCreatorManager manager)
		{
			if (!((Object)(object)manager?.FactionListParent != (Object)null))
			{
				return null;
			}
			return ((Component)manager.FactionListParent).GetComponentInParent<ScrollRect>();
		}

		internal static bool IsHorizontalLayout(RectTransform listParent)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)listParent != (Object)null)
			{
				Rect rect = listParent.rect;
				float width = ((Rect)(ref rect)).width;
				rect = listParent.rect;
				return width >= ((Rect)(ref rect)).height;
			}
			return false;
		}

		internal static void UpdateDragScroll(ScrollRect scrollRect, Vector2 screenPosition, Camera eventCamera)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)scrollRect == (Object)null)
			{
				return;
			}
			RectTransform val = (RectTransform)(((Object)(object)scrollRect.viewport != (Object)null) ? ((object)scrollRect.viewport) : ((object)/*isinst with value type is only supported in some contexts*/));
			Vector2 val2 = default(Vector2);
			if ((Object)(object)val == (Object)null || !RectTransformUtility.ScreenPointToLocalPointInRectangle(val, screenPosition, eventCamera, ref val2))
			{
				return;
			}
			Rect rect = val.rect;
			float unscaledDeltaTime = Time.unscaledDeltaTime;
			if (scrollRect.horizontal)
			{
				float num = val2.x - ((Rect)(ref rect)).xMin;
				float num2 = ((Rect)(ref rect)).xMax - val2.x;
				float num3 = 0f;
				if (num < 72f)
				{
					num3 = (0f - Mathf.InverseLerp(72f, 0f, num)) * 2.5f * unscaledDeltaTime;
				}
				else if (num2 < 72f)
				{
					num3 = Mathf.InverseLerp(72f, 0f, num2) * 2.5f * unscaledDeltaTime;
				}
				if (Mathf.Abs(num3) > 0.0001f)
				{
					scrollRect.horizontalNormalizedPosition = Mathf.Clamp01(scrollRect.horizontalNormalizedPosition + num3);
				}
			}
			if (scrollRect.vertical)
			{
				float num4 = val2.y - ((Rect)(ref rect)).yMin;
				float num5 = ((Rect)(ref rect)).yMax - val2.y;
				float num6 = 0f;
				if (num4 < 72f)
				{
					num6 = (0f - Mathf.InverseLerp(72f, 0f, num4)) * 2.5f * unscaledDeltaTime;
				}
				else if (num5 < 72f)
				{
					num6 = Mathf.InverseLerp(72f, 0f, num5) * 2.5f * unscaledDeltaTime;
				}
				if (Mathf.Abs(num6) > 0.0001f)
				{
					scrollRect.verticalNormalizedPosition = Mathf.Clamp01(scrollRect.verticalNormalizedPosition + num6);
				}
			}
		}

		internal static int GetInsertionIndex(FactionCreatorManager manager, Vector2 screenPosition, Camera camera, Transform ignore, int currentIndex = -1)
		{
			//IL_0026: 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_004a: 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_0092: 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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = manager?.FactionListParent;
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if ((Object)(object)val == (Object)null || ((Transform)val).childCount == 0)
			{
				return 0;
			}
			Vector2 val2 = default(Vector2);
			if (!RectTransformUtility.ScreenPointToLocalPointInRectangle(val, screenPosition, camera, ref val2))
			{
				return Mathf.Clamp(currentIndex, 0, ((Transform)val).childCount);
			}
			bool flag = IsHorizontalLayout(val);
			float num = (flag ? val2.x : val2.y);
			int num2 = 0;
			for (int i = 0; i < ((Transform)val).childCount; i++)
			{
				Transform child = ((Transform)val).GetChild(i);
				RectTransform val3 = (RectTransform)(object)((child is RectTransform) ? child : null);
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3 == (Object)(object)ignore))
				{
					Rect rect = val3.rect;
					Vector3 val4 = ((Transform)val).InverseTransformPoint(((Transform)val3).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center)));
					float num3 = (flag ? val4.x : val4.y);
					if (num > num3)
					{
						num2 = i + 1;
					}
				}
			}
			num2 = Mathf.Clamp(num2, 0, ((Transform)val).childCount);
			if (currentIndex < 0)
			{
				return num2;
			}
			if (num2 == currentIndex)
			{
				return currentIndex;
			}
			if (Mathf.Abs(num2 - currentIndex) > 1)
			{
				num2 = currentIndex + ((num2 > currentIndex) ? 1 : (-1));
			}
			return num2;
		}

		private static IList GetAddedUnits(FactionCreatorManager manager)
		{
			return AddedUnitsField?.GetValue(manager) as IList;
		}

		private static UnitButtonBase GetSpawnedButton(object wrapper)
		{
			object? obj = (_spawnedButtonField ?? (_spawnedButtonField = AccessTools.Field(AccessTools.Inner(typeof(FactionCreatorManager), "SpawnedWrapper"), "spawnedButton")))?.GetValue(wrapper);
			return (UnitButtonBase)((obj is UnitButtonBase) ? obj : null);
		}
	}
	internal static class FactionCreatorUnitCostHover
	{
		private static readonly FieldInfo UnitCostField = AccessTools.Field(typeof(UnitButtonBase), "UnitCost");

		private static readonly FieldInfo TargetIconColorField = AccessTools.Field(typeof(UnitButtonBase), "targetIconColor");

		private static readonly MethodInfo GetUnitMethod = AccessTools.Method(typeof(UnitButtonBase), "GetUnit", (Type[])null, (Type[])null);

		private static readonly PropertyInfo IsCustomUnitProperty = AccessTools.Property(AccessTools.TypeByName("Landfall.TABS.UnitBlueprint"), "IsCustomUnit");

		private static readonly MethodInfo GetUnitCostMethod = AccessTools.Method(AccessTools.TypeByName("Landfall.TABS.UnitBlueprint"), "GetUnitCost", new Type[1] { typeof(bool) }, (Type[])null);

		private static PropertyInfo _costTextProperty;

		private static readonly Color DimIconColor = new Color(0.32f, 0.32f, 0.32f, 1f);

		internal static bool IsFactionEditorUnitButton(UnitButtonBase button)
		{
			if ((Object)(object)button == (Object)null)
			{
				return false;
			}
			if (button is UnitButtonFactionCreator)
			{
				return true;
			}
			if (((object)button).GetType().Name == "FactionCreatorUnitBrowserUnitButton")
			{
				return true;
			}
			if (!((Object)(object)((Component)button).GetComponentInParent<FactionCreatorManager>() != (Object)null))
			{
				return (Object)(object)((Component)button).GetComponentInParent<FactionCreatorUnitBrowser>() != (Object)null;
			}
			return true;
		}

		internal static void ShowOnHover(UnitButtonBase button)
		{
			if (!IsFactionEditorUnitButton(button))
			{
				return;
			}
			object obj = GetUnitMethod?.Invoke(button, null);
			if (obj != null && IsCustomUnit(obj))
			{
				string unitCostText = GetUnitCostText(obj);
				if (unitCostText != null)
				{
					DimIcon(button);
					ShowCostOverlay(button, unitCostText);
				}
			}
		}

		internal static void HideOnHover(UnitButtonBase button)
		{
			if (IsFactionEditorUnitButton(button))
			{
				object obj = GetUnitMethod?.Invoke(button, null);
				if (obj != null && IsCustomUnit(obj))
				{
					RestoreIcon(button);
					HideCostOverlay(button);
				}
			}
		}

		private static bool IsCustomUnit(object unit)
		{
			if (IsCustomUnitProperty != null)
			{
				return (bool)IsCustomUnitProperty.GetValue(unit);
			}
			return false;
		}

		private static string GetUnitCostText(object unit)
		{
			if (GetUnitCostMethod == null)
			{
				return null;
			}
			return GetUnitCostMethod.Invoke(unit, new object[1] { true })?.ToString();
		}

		private static void DimIcon(UnitButtonBase button)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			TargetIconColorField?.SetValue(button, 1f);
			Image iconImage = button.IconImage;
			if ((Object)(object)iconImage != (Object)null)
			{
				((Graphic)iconImage).color = DimIconColor;
			}
		}

		private static void RestoreIcon(UnitButtonBase button)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			TargetIconColorField?.SetValue(button, 0f);
			Image iconImage = button.IconImage;
			if ((Object)(object)iconImage != (Object)null)
			{
				((Graphic)iconImage).color = Color.white;
			}
		}

		private static void ShowCostOverlay(UnitButtonBase button, string costText)
		{
			//IL_00c9: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			object? obj = UnitCostField?.GetValue(button);
			Behaviour val = (Behaviour)((obj is Behaviour) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Transform transform = ((Component)val).transform;
			RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			RectTransform val3 = (((Object)(object)button.IconImage != (Object)null) ? ((Graphic)button.IconImage).rectTransform : null);
			if (!((Object)(object)val2 == (Object)null))
			{
				FactionCreatorCostHoverState.GetOrCreate(button).CaptureCostLayout(val2);
				if ((Object)(object)val3 != (Object)null)
				{
					((Transform)val2).SetParent(((Transform)val3).parent, false);
					val2.anchorMin = val3.anchorMin;
					val2.anchorMax = val3.anchorMax;
					val2.pivot = new Vector2(0.5f, 0.5f);
					val2.anchoredPosition = val3.anchoredPosition;
					val2.sizeDelta = val3.sizeDelta;
				}
				else
				{
					val2.anchorMin = new Vector2(0.5f, 0.5f);
					val2.anchorMax = new Vector2(0.5f, 0.5f);
					val2.pivot = new Vector2(0.5f, 0.5f);
					val2.anchoredPosition = Vector2.zero;
				}
				((Transform)val2).SetAsLastSibling();
				SetText((Component)(object)val, costText);
				val.enabled = true;
				((Component)val).gameObject.SetActive(true);
				PropertyInfo property = ((object)val).GetType().GetProperty("color");
				if (property != null)
				{
					Color val4 = (Color)property.GetValue(val, null);
					val4 = Color.white;
					val4.a = 1f;
					property.SetValue(val, val4, null);
				}
			}
		}

		private static void HideCostOverlay(UnitButtonBase button)
		{
			object? obj = UnitCostField?.GetValue(button);
			Behaviour val = (Behaviour)((obj is Behaviour) ? obj : null);
			if (!((Object)(object)val == (Object)null))
			{
				val.enabled = false;
				Transform transform = ((Component)val).transform;
				RectTransform costRect = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				((Component)button).GetComponent<FactionCreatorCostHoverState>()?.RestoreCostLayout(costRect);
			}
		}

		private static void SetText(Component textComponent, string value)
		{
			if (!((Object)(object)textComponent == (Object)null))
			{
				if ((object)_costTextProperty == null)
				{
					_costTextProperty = ((object)textComponent).GetType().GetProperty("text");
				}
				_costTextProperty?.SetValue(textComponent, value, null);
			}
		}
	}
	internal sealed class FactionCreatorUnitDragReorder : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		private static readonly Vector3[] WorldCorners = (Vector3[])(object)new Vector3[4];

		private FactionCreatorManager _manager;

		private UnitButtonBase _button;

		private RectTransform _rectTransform;

		private RectTransform _canvasRect;

		private Canvas _canvas;

		private Camera _eventCamera;

		private Transform _listParent;

		private RectTransform _listParentRect;

		private RectTransform _dropGap;

		private ScrollRect _scrollRect;

		private FactionCreatorDragScrollSession _scrollSession;

		private bool _horizontalLayout;

		private int _targetIndex;

		private int _fromIndex;

		private bool _moved;

		private bool _suppressClick;

		private CanvasGroup _canvasGroup;

		private Vector2 _currentScreenPosition;

		internal Vector2 CurrentScreenPosition => _currentScreenPosition;

		internal void Initialize(FactionCreatorManager manager, UnitButtonBase button)
		{
			_manager = manager;
			_button = button;
			ref RectTransform rectTransform = ref _rectTransform;
			Transform transform = ((Component)this).transform;
			rectTransform = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			_canvas = ((Component)this).GetComponentInParent<Canvas>();
			_canvasRect = (RectTransform)(((Object)(object)_canvas != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
		}

		internal bool ConsumeClickSuppression()
		{
			if (!_suppressClick)
			{
				return false;
			}
			_suppressClick = false;
			return true;
		}

		public void OnBeginDrag(PointerEventData eventData)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_manager == (Object)null) && !((Object)(object)_button == (Object)null) && !((Object)(object)_rectTransform == (Object)null) && !((Object)(object)_canvasRect == (Object)null) && (int)eventData.button == 0 && FactionCreatorReorderLogic.GetUnitIndex(_manager, _button) >= 0)
			{
				_fromIndex = ((Component)_button).transform.GetSiblingIndex();
				_targetIndex = _fromIndex;
				_moved = false;
				_listParent = _manager.FactionListParent;
				ref RectTransform listParentRect = ref _listParentRect;
				Transform listParent = _listParent;
				listParentRect = (RectTransform)(object)((listParent is RectTransform) ? listParent : null);
				_horizontalLayout = FactionCreatorReorderLogic.IsHorizontalLayout(_listParentRect);
				_scrollRect = FactionCreatorReorderLogic.FindListScrollRect(_manager);
				object obj = eventData.pressEventCamera;
				if (obj == null)
				{
					Canvas canvas = _canvas;
					obj = ((canvas != null) ? canvas.worldCamera : null);
				}
				_eventCamera = (Camera)obj;
				_canvasGroup = ((Component)this).gameObject.GetComponent<CanvasGroup>();
				if ((Object)(object)_canvasGroup == (Object)null)
				{
					_canvasGroup = ((Component)this).gameObject.AddComponent<CanvasGroup>();
				}
				_dropGap = FactionCreatorDropGap.Create(_listParentRect, _rectTransform, _horizontalLayout);
				((Transform)_dropGap).SetSiblingIndex(_fromIndex);
				((Component)this).transform.SetParent((Transform)(object)_canvasRect, true);
				_canvasGroup.blocksRaycasts = false;
				_canvasGroup.alpha = 0.85f;
				((Component)this).transform.SetAsLastSibling();
				_currentScreenPosition = eventData.position;
				if ((Object)(object)_scrollRect != (Object)null)
				{
					_scrollSession = ((Component)this).gameObject.AddComponent<FactionCreatorDragScrollSession>();
					_scrollSession.Begin(_scrollRect, _eventCamera, this);
				}
				SnapCenterToCursor(eventData);
				UpdateDropTarget(_currentScreenPosition);
			}
		}

		public void OnDrag(PointerEventData eventData)
		{
			//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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_manager == (Object)null))
			{
				Vector2 delta = eventData.delta;
				if (((Vector2)(ref delta)).sqrMagnitude > 0.01f)
				{
					_moved = true;
				}
				_currentScreenPosition = eventData.position;
				SnapCenterToCursor(eventData);
				UpdateDropTarget(_currentScreenPosition);
			}
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			if (!((Object)(object)_manager == (Object)null) && !((Object)(object)_listParent == (Object)null))
			{
				if ((Object)(object)_scrollSession != (Object)null)
				{
					Object.Destroy((Object)(object)_scrollSession);
					_scrollSession = null;
				}
				FactionCreatorDropGap.Destroy(_dropGap);
				_dropGap = null;
				((Component)this).transform.SetParent(_listParent, false);
				((Component)this).transform.SetSiblingIndex(_targetIndex);
				if (_moved)
				{
					FactionCreatorReorderLogic.SyncAddedUnitsFromHierarchy(_manager);
					_suppressClick = true;
				}
				if ((Object)(object)_canvasGroup != (Object)null)
				{
					_canvasGroup.blocksRaycasts = true;
					_canvasGroup.alpha = 1f;
				}
				if ((Object)(object)_listParentRect != (Object)null)
				{
					LayoutRebuilder.ForceRebuildLayoutImmediate(_listParentRect);
				}
			}
		}

		private void UpdateDropTarget(Vector2 screenPosition)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			int insertionIndex = FactionCreatorReorderLogic.GetInsertionIndex(_manager, screenPosition, _eventCamera, (Transform)(object)_dropGap, _targetIndex);
			if (insertionIndex == _targetIndex)
			{
				return;
			}
			_targetIndex = insertionIndex;
			if ((Object)(object)_dropGap != (Object)null)
			{
				((Transform)_dropGap).SetSiblingIndex(_targetIndex);
				if ((Object)(object)_listParentRect != (Object)null)
				{
					LayoutRebuilder.ForceRebuildLayoutImmediate(_listParentRect);
				}
			}
		}

		private void SnapCenterToCursor(PointerEventData eventData)
		{
			//IL_0016: 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_0026: 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_0035: 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_0056: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			_rectTransform.GetWorldCorners(WorldCorners);
			Vector3 val = (WorldCorners[0] + WorldCorners[2]) * 0.5f;
			Vector3 val2 = default(Vector3);
			if (RectTransformUtility.ScreenPointToWorldPointInRectangle(_canvasRect, eventData.position, ((Object)(object)_canvas != (Object)null && (int)_canvas.renderMode == 0) ? null : _eventCamera, ref val2))
			{
				RectTransform rectTransform = _rectTransform;
				((Transform)rectTransform).position = ((Transform)rectTransform).position + (val2 - val);
			}
		}
	}
	internal static class GameStatePatches
	{
		public static void EnterBattleState_Postfix()
		{
			BarrelRollerDeathLogic.ResetBattleCaches();
			WaterPatches.ResetRiverFlowDirections();
			MirrorShieldLogic.ResetBattleState();
		}
	}
	internal static class GasGrenadePatches
	{
		private const float FloorNormalMin = 0.45f;

		private const float DownwardProbeDistance = 0.75f;

		private static readonly int MapLayer = LayerMask.NameToLayer("Map");

		[ThreadStatic]
		private static int _floorCatchFrame = -1;

		[ThreadStatic]
		private static int _floorCatchProjectileId;

		public static void ProjectileHit_DisableProjectile_Postfix(ProjectileHit __instance)
		{
			//IL_0022: 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)
			if (IsGasGrenade((Component)(object)__instance))
			{
				MoveTransform component = ((Component)__instance).GetComponent<MoveTransform>();
				if (!((Object)(object)component == (Object)null))
				{
					((Behaviour)component).enabled = false;
					component.velocity = Vector3.zero;
				}
			}
		}

		public static void RaycastTrail_Check_Postfix(RaycastTrail __instance)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			if (!IsGasGrenade((Component)(object)__instance))
			{
				return;
			}
			ProjectileHit component = ((Component)__instance).GetComponent<ProjectileHit>();
			if ((Object)(object)component == (Object)null || component.done)
			{
				return;
			}
			MoveTransform component2 = ((Component)__instance).GetComponent<MoveTransform>();
			if (!((Object)(object)component2 == (Object)null) && ((Behaviour)component2).enabled && TryFindFloorImpact(((Component)__instance).transform.position, component2.velocity, __instance.mask, out var hitInfo))
			{
				int instanceID = ((Object)component).GetInstanceID();
				if (_floorCatchFrame != Time.frameCount || _floorCatchProjectileId != instanceID)
				{
					_floorCatchFrame = Time.frameCount;
					_floorCatchProjectileId = instanceID;
					((Component)__instance).transform.position = ((RaycastHit)(ref hitInfo)).point;
					component.Hit(hitInfo, 1f);
				}
			}
		}

		private static bool IsGasGrenade(Component component)
		{
			if ((Object)(object)component != (Object)null)
			{
				return ((Object)component.gameObject).name.IndexOf("Grenade_Gas", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static bool TryFindFloorImpact(Vector3 position, Vector3 velocity, LayerMask mask, out RaycastHit hitInfo)
		{
			//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_002a: 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_0015: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			hitInfo = default(RaycastHit);
			if (velocity.y <= 0.25f && TryMapFloorHit(position, Vector3.down, 0.75f, mask, out hitInfo))
			{
				return true;
			}
			if (velocity.y > -0.5f || Mathf.Abs(velocity.y) < ((Vector3)(ref velocity)).magnitude * 0.35f)
			{
				return false;
			}
			Vector3 val = velocity * Time.deltaTime;
			if (((Vector3)(ref val)).sqrMagnitude <= 1E-06f)
			{
				return false;
			}
			return TryMapFloorHit(position - val, ((Vector3)(ref val)).normalized, ((Vector3)(ref val)).magnitude + 0.2f, mask, out hitInfo);
		}

		private static bool TryMapFloorHit(Vector3 origin, Vector3 direction, float distance, LayerMask mask, out RaycastHit hitInfo)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: