Decompiled source of Gabrielings v0.5.8

Gabrielings.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using Gabrielings.Components;
using Gabrielings.Configuration;
using Gabrielings.Systems;
using Gabrielings.Utilities;
using HarmonyLib;
using PluginConfig.API;
using PluginConfig.API.Decorators;
using PluginConfig.API.Fields;
using ULTRAKILL.Cheats;
using ULTRAKILL.Enemy;
using ULTRAKILL.Portal;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Gabrielings")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+1b981e1d24f7faeeb07a02c1e5687e9c81e173dc")]
[assembly: AssemblyProduct("Gabrielings")]
[assembly: AssemblyTitle("Gabrielings")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Gabrielings
{
	[BepInPlugin("grabelings.kiyroprower.ultrakill", "Grabielings", "0.5.8")]
	[BepInProcess("ULTRAKILL.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "grabelings.kiyroprower.ultrakill";

		public const string NAME = "Grabielings";

		public const string VERSION = "0.5.8";

		public const string PLUGIN_CONFIGURATOR_GUID = "com.eternalUnion.pluginConfigurator";

		private Harmony _harmony;

		private bool _quittingHooked;

		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			GabrielingsConfig.Initialize(((BaseUnityPlugin)this).Logger);
			PowerSpawnManager.Initialize();
			if (!GabrielingsConfig.Enabled)
			{
				Log.LogInfo((object)"Gabrielings is disabled in config — patches will stay idle until re-enabled.");
			}
			_harmony = new Harmony("grabelings.kiyroprower.ultrakill");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			Log.LogInfo((object)"Harmony patches applied for Grabielings v0.5.8.");
			if (!_quittingHooked)
			{
				Application.quitting += OnApplicationQuitting;
				_quittingHooked = true;
			}
			PowerSpawnManager.Reset();
			LogDebug("Spawn manager reset during plugin awake.");
		}

		private void Update()
		{
			PowerSpawnManager.Tick();
		}

		public bool Unload()
		{
			PowerSpawnManager.Shutdown();
			if (_quittingHooked)
			{
				Application.quitting -= OnApplicationQuitting;
				_quittingHooked = false;
			}
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
				_harmony = null;
			}
			Instance = null;
			Log = null;
			return true;
		}

		private void OnApplicationQuitting()
		{
			PowerSpawnManager.Reset();
		}

		public static void LogDebug(string message)
		{
			if (GabrielingsConfig.DebugLogging && !string.IsNullOrEmpty(message))
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)("[Debug] " + message));
				}
			}
		}
	}
}
namespace Gabrielings.Utilities
{
	public static class EnemyFilter
	{
		public static bool IsPlayer(EnemyIdentifier eid)
		{
			if ((Object)(object)eid == (Object)null || (Object)(object)((Component)eid).gameObject == (Object)null)
			{
				return false;
			}
			NewMovement instance = MonoSingleton<NewMovement>.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				return (Object)(object)((Component)instance).gameObject == (Object)(object)((Component)eid).gameObject;
			}
			return false;
		}

		public static bool IsGabrielPower(EnemyIdentifier eid)
		{
			if ((Object)(object)eid == (Object)null)
			{
				return false;
			}
			GabrielPower gabrielPower = default(GabrielPower);
			return ((Component)eid).TryGetComponent<GabrielPower>(ref gabrielPower);
		}

		public static bool IsArenaTarget(EnemyIdentifier eid)
		{
			if ((Object)(object)eid == (Object)null || eid.dead)
			{
				return false;
			}
			if (IsPlayer(eid))
			{
				return false;
			}
			if (IsGabrielPower(eid))
			{
				return false;
			}
			if (IsIgnoredSupportEnemy(eid))
			{
				return false;
			}
			if (IsDamageImmune(eid))
			{
				return false;
			}
			return true;
		}

		public static bool IsIgnoredSupportEnemy(EnemyIdentifier eid)
		{
			if (!IsIgnoredIdol(eid))
			{
				return IsIgnoredDeathcatcher(eid);
			}
			return true;
		}

		public static bool IsIgnoredIdol(EnemyIdentifier eid)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			if ((Object)(object)eid == (Object)null)
			{
				return false;
			}
			if ((int)eid.enemyType != 21)
			{
				return (Object)(object)((Component)eid).GetComponent<Idol>() != (Object)null;
			}
			return true;
		}

		public static bool IsIgnoredDeathcatcher(EnemyIdentifier eid)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Invalid comparison between Unknown and I4
			if ((Object)(object)eid == (Object)null)
			{
				return false;
			}
			if ((int)eid.enemyType != 39)
			{
				return (Object)(object)((Component)eid).GetComponent<Deathcatcher>() != (Object)null;
			}
			return true;
		}

		public static bool IsDamageImmune(EnemyIdentifier eid)
		{
			if ((Object)(object)eid == (Object)null)
			{
				return true;
			}
			if (InvincibleEnemies.Enabled || eid.blessed)
			{
				return true;
			}
			return eid.totalDamageTakenMultiplier <= 0f;
		}
	}
	public static class PowerPrefabExtractor
	{
		private static GameObject _cachedPrefab;

		public static GameObject ResolvePrefab()
		{
			if ((Object)(object)_cachedPrefab != (Object)null)
			{
				return _cachedPrefab;
			}
			GameObject val = FindInLoadedScenes();
			if ((Object)(object)val != (Object)null)
			{
				_cachedPrefab = val;
				return _cachedPrefab;
			}
			val = FindInResources();
			if ((Object)(object)val != (Object)null)
			{
				_cachedPrefab = val;
				return _cachedPrefab;
			}
			val = TryAddressables();
			if ((Object)(object)val != (Object)null)
			{
				_cachedPrefab = val;
				return _cachedPrefab;
			}
			return null;
		}

		public static void Invalidate()
		{
			_cachedPrefab = null;
		}

		private static GameObject FindInLoadedScenes()
		{
			return FindInResources();
		}

		private static GameObject FindInResources()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Power[] array = Resources.FindObjectsOfTypeAll<Power>();
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] == (Object)null)
				{
					continue;
				}
				GameObject gameObject = ((Component)array[i]).gameObject;
				if (!((Object)(object)gameObject == (Object)null))
				{
					Scene scene = gameObject.scene;
					if (!((Scene)(ref scene)).IsValid())
					{
						return gameObject;
					}
				}
			}
			for (int j = 0; j < array.Length; j++)
			{
				if ((Object)(object)array[j] != (Object)null && (Object)(object)((Component)array[j]).gameObject != (Object)null)
				{
					return ((Component)array[j]).gameObject;
				}
			}
			return null;
		}

		private static GameObject TryAddressables()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			string[] array = new string[4] { "Assets/Prefabs/Enemies/Power.prefab", "Assets/Prefabs/Enemies/Power", "Power", "Enemies/Power" };
			for (int i = 0; i < array.Length; i++)
			{
				try
				{
					AsyncOperationHandle<GameObject> val = Addressables.LoadAssetAsync<GameObject>((object)array[i]);
					if (val.IsValid())
					{
						GameObject val2 = val.WaitForCompletion();
						if ((Object)(object)val2 != (Object)null)
						{
							return val2;
						}
					}
				}
				catch
				{
				}
			}
			return null;
		}
	}
}
namespace Gabrielings.Systems
{
	public static class PowerSpawnManager
	{
		private static readonly List<GameObject> _alivePowers = new List<GameObject>(8);

		private static readonly List<GameObject> _managedProjectiles = new List<GameObject>(16);

		private static readonly List<EnemyIdentifier> _trackedEnemies = new List<EnemyIdentifier>(32);

		private static readonly Dictionary<EnemyIdentifier, int> _enemyDamageFrames = new Dictionary<EnemyIdentifier, int>(16);

		private static readonly Dictionary<SwingCheck2, List<EnemyIdentifier>> _managedMeleeHitEnemies = new Dictionary<SwingCheck2, List<EnemyIdentifier>>(16);

		private static readonly Collider[] EmptyColliders = (Collider[])(object)new Collider[0];

		private static readonly MethodInfo PowerBackdashMethod = typeof(Power).GetMethod("Backdash", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[1] { typeof(bool) }, null);

		private static readonly object[] PowerBackdashAnimationArgs = new object[1] { true };

		private const float LockedDoorInitialScanDelay = 0.25f;

		private const float LockedDoorRetryDelay = 0.5f;

		private const float LockedDoorScanTimeout = 8f;

		private const float OpenAreaSignalCooldown = 1f;

		private const float OpenMapTargetMaxPlayerDistance = 55f;

		private const float WaveSettleDelay = 1.25f;

		private const float ManagedPowerProjectileOwnerSearchDistance = 18f;

		private const int EarthmoverMissionNumber = 29;

		private const float FollowMinDistance = 7f;

		private const float FollowMaxDistance = 22f;

		private const float FollowTeleportDistance = 70f;

		private const float ProvidenceHookDodgeForce = 750f;

		private const float ProvidenceHookDodgeRayDistance = 7f;

		private const float ProvidenceHookDodgeRepeatDelay = 0.1f;

		private const string PowerDodgeAnimationState = "Backdash";

		private const float PlayerCollisionRefreshInterval = 0.5f;

		public const EnemyType ManagedPowerSurrogateType = (EnemyType)37;

		private static ActivateArena _trackedArena;

		private static Door _pendingLockedDoor;

		private static bool _pendingOpenAreaScan;

		private static float _pendingLockedDoorTimer;

		private static float _pendingLockedDoorTimeout;

		private static float _openAreaSignalCooldown;

		private static float _clearGraceTimer;

		private static int _remainingEnemySnapshot;

		private static bool _targetByPlayerProximity;

		private static bool _initialized;

		private static int _managedPowerProjectileParryDepth;

		public static void Initialize()
		{
			if (!_initialized)
			{
				EnemyTracker.onEnemyAdded = (Action<EnemyIdentifier>)Delegate.Combine(EnemyTracker.onEnemyAdded, new Action<EnemyIdentifier>(HandleEnemyAdded));
				StatsManager.checkpointRestart += OnCheckpointRestart;
				_initialized = true;
				Plugin.LogDebug("Power spawn manager subscribed to enemy and checkpoint events.");
			}
		}

		public static void Shutdown()
		{
			if (_initialized)
			{
				EnemyTracker.onEnemyAdded = (Action<EnemyIdentifier>)Delegate.Remove(EnemyTracker.onEnemyAdded, new Action<EnemyIdentifier>(HandleEnemyAdded));
				StatsManager.checkpointRestart -= OnCheckpointRestart;
				_initialized = false;
			}
			Reset();
		}

		public static void Reset()
		{
			DespawnAll(silent: true);
			_trackedEnemies.Clear();
			_enemyDamageFrames.Clear();
			_managedMeleeHitEnemies.Clear();
			_trackedArena = null;
			_pendingLockedDoor = null;
			_pendingOpenAreaScan = false;
			_pendingLockedDoorTimer = 0f;
			_pendingLockedDoorTimeout = 0f;
			_openAreaSignalCooldown = 0f;
			_clearGraceTimer = 0f;
			_remainingEnemySnapshot = 0;
			_targetByPlayerProximity = false;
			_managedPowerProjectileParryDepth = 0;
		}

		public static void HandleArenaActivated(ActivateArena arena)
		{
			if (!GabrielingsConfig.Enabled)
			{
				Plugin.LogDebug("Arena activation ignored because the mod is disabled.");
				return;
			}
			if (!CanAssistArena(arena))
			{
				Plugin.LogDebug("Arena activation ignored because it is not a player combat arena.");
				return;
			}
			if ((Object)(object)_trackedArena != (Object)null && (Object)(object)_trackedArena != (Object)(object)arena)
			{
				Plugin.LogDebug("New arena activation detected while another arena was tracked; despawning old allies.");
				DespawnAll();
			}
			else if ((Object)(object)_trackedArena == (Object)null && _alivePowers.Count > 0)
			{
				Plugin.LogDebug("New arena activation detected while a fallback assist was active; despawning old allies.");
				DespawnAll();
			}
			_trackedArena = arena;
			_pendingLockedDoor = null;
			_pendingOpenAreaScan = false;
			_pendingLockedDoorTimer = 0f;
			_pendingLockedDoorTimeout = 0f;
			_targetByPlayerProximity = false;
			_trackedEnemies.Clear();
			CollectArenaTargets(arena, _trackedEnemies);
			_remainingEnemySnapshot = CountRemainingTrackedEnemies();
			if (_remainingEnemySnapshot <= 0)
			{
				Plugin.LogDebug("Arena has no direct enemy targets; scheduling fallback scan.");
				Door val = FindFirstDoor(arena);
				_trackedEnemies.Clear();
				_trackedArena = null;
				if ((Object)(object)val != (Object)null)
				{
					ScheduleLockedDoorAssist(val, "arena without direct targets");
				}
				else
				{
					ScheduleOpenAreaAssist("arena without direct targets");
				}
			}
			else
			{
				Plugin.LogDebug($"Arena activation accepted with {_remainingEnemySnapshot} tracked enemies.");
				_clearGraceTimer = 0f;
				SpawnPowers(GabrielingsConfig.PowerCount);
			}
		}

		public static void HandleDoorLocked(Door door)
		{
			if (!GabrielingsConfig.Enabled)
			{
				Plugin.LogDebug("Door lock ignored because the mod is disabled.");
			}
			else
			{
				ScheduleLockedDoorAssist(door, "door lock");
			}
		}

		public static void HandleBossHealthBar(BossHealthBar bossBar)
		{
			if (!GabrielingsConfig.Enabled)
			{
				Plugin.LogDebug("Boss assist ignored because the mod is disabled.");
				return;
			}
			if (!GabrielingsConfig.AssistBosses)
			{
				Plugin.LogDebug("Boss assist ignored because boss assists are disabled.");
				return;
			}
			if (IsEarthmoverFakeBossBar(bossBar))
			{
				Plugin.LogDebug("Boss assist ignored for 7-4's global Earthmover boss bar.");
				return;
			}
			EnemyIdentifier val = ResolveBossEnemy(bossBar);
			if (!IsValidAssistTarget(val))
			{
				Plugin.LogDebug("Boss health bar detected, but no valid boss EnemyIdentifier was resolved.");
				return;
			}
			if (!_trackedEnemies.Contains(val))
			{
				_trackedEnemies.Add(val);
				_remainingEnemySnapshot = CountRemainingTrackedEnemies();
				Plugin.LogDebug("Boss target tracked: " + DescribeEnemy(val) + ".");
			}
			_pendingLockedDoor = null;
			_pendingOpenAreaScan = false;
			_pendingLockedDoorTimer = 0f;
			_pendingLockedDoorTimeout = 0f;
			_targetByPlayerProximity = false;
			if (_alivePowers.Count == 0)
			{
				Plugin.LogDebug("Spawning ally Powers for boss encounter.");
				SpawnPowers(GabrielingsConfig.PowerCount);
			}
		}

		public static void HandleCheckpointActivated(CheckPoint checkpoint)
		{
			if (HasActiveState())
			{
				Plugin.LogDebug("Checkpoint activated; clearing active ally Powers and pending scans.");
				Reset();
			}
		}

		public static void HandleCheckpointRestart(string source)
		{
			if (HasActiveState())
			{
				Plugin.LogDebug("Checkpoint restart from " + source + "; clearing active ally Powers and pending scans.");
				Reset();
			}
		}

		public static void HandlePlayerDeath()
		{
			if (HasActiveState())
			{
				Plugin.LogDebug("Player death detected; clearing active ally Powers and pending scans.");
				Reset();
			}
		}

		public static void NotifyPowerKilledEnemy(EnemyIdentifier enemy)
		{
			if (!((Object)(object)enemy == (Object)null) && _trackedEnemies.Contains(enemy))
			{
				_remainingEnemySnapshot = CountRemainingTrackedEnemies();
				Plugin.LogDebug($"Tracked enemy died; {_remainingEnemySnapshot} enemies remain.");
				if (_remainingEnemySnapshot <= 0)
				{
					StartClearGrace("tracked enemy death");
				}
			}
		}

		public static void HandleEnemyTargetUpdated(EnemyIdentifier eid)
		{
			if (!GabrielingsConfig.Enabled || (Object)(object)eid == (Object)null)
			{
				return;
			}
			if (_alivePowers.Count > 0 || _trackedEnemies.Count > 0)
			{
				if (IsOpenAreaCombatTarget(eid))
				{
					AddWaveTarget(eid);
				}
			}
			else if (GabrielingsConfig.ExtendedEnemyCheck && !((Object)(object)_pendingLockedDoor != (Object)null) && !_pendingOpenAreaScan && !(_openAreaSignalCooldown > 0f) && IsOpenAreaCombatTarget(eid))
			{
				_openAreaSignalCooldown = 1f;
				ScheduleOpenAreaAssist("open-map combat target " + DescribeEnemy(eid));
			}
		}

		public static void ConfigureManagedPowerProjectile(Projectile projectile)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			if ((Object)(object)projectile == (Object)null || (int)projectile.safeEnemyType != 40 || projectile.friendly || projectile.playerBullet)
			{
				return;
			}
			GabrielPower gabrielPower = FindNearestManagedPower(((Component)projectile).transform.position, 18f);
			if ((Object)(object)gabrielPower == (Object)null)
			{
				return;
			}
			GabrielPowerProjectile gabrielPowerProjectile = ((Component)projectile).GetComponent<GabrielPowerProjectile>();
			if ((Object)(object)gabrielPowerProjectile == (Object)null)
			{
				gabrielPowerProjectile = ((Component)projectile).gameObject.AddComponent<GabrielPowerProjectile>();
			}
			gabrielPowerProjectile.Owner = gabrielPower;
			gabrielPowerProjectile.OriginalSafeEnemyType = projectile.safeEnemyType;
			projectile.sourceWeapon = ((Component)gabrielPower).gameObject;
			TrackManagedProjectile(projectile);
			EnemyIdentifier val = SelectPowerTarget(((Component)projectile).transform.position, gabrielPower.CurrentTarget);
			if (!IsValidActiveTarget(val))
			{
				gabrielPowerProjectile.Target = null;
				projectile.targetHandle = null;
				projectile.isTargetPlayer = false;
				projectile.target = null;
				DestroyManagedProjectile(projectile);
				Plugin.LogDebug("Managed Power projectile was despawned because no active enemy target was available.");
				return;
			}
			gabrielPowerProjectile.Target = val;
			TargetHandle val2 = CreateTargetHandle(val);
			if (val2 != (TargetHandle)null)
			{
				projectile.targetHandle = val2;
			}
			projectile.isTargetPlayer = false;
			projectile.target = new EnemyTarget(val);
			Plugin.LogDebug("Configured managed Power projectile target: " + DescribeEnemy(val) + ".");
		}

		public static void PrepareManagedPowerProjectileHit(Projectile projectile, Collider other)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			//IL_005b: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)projectile == (Object)null || (Object)(object)other == (Object)null || (int)projectile.safeEnemyType != 40)
			{
				return;
			}
			GabrielPowerProjectile component = ((Component)projectile).GetComponent<GabrielPowerProjectile>();
			EnemyIdentifier val = (((Object)(object)component == (Object)null) ? null : component.Target);
			if (!IsManagedPowerTarget(val))
			{
				return;
			}
			EnemyIdentifier val2 = ResolveColliderEnemy(other);
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 != (Object)(object)val) && val2.enemyType == projectile.safeEnemyType)
			{
				projectile.safeEnemyType = (EnemyType)37;
				TargetHandle val3 = CreateTargetHandle(val2);
				if (val3 != (TargetHandle)null)
				{
					projectile.targetHandle = val3;
				}
				Plugin.LogDebug("Prepared managed Power projectile friendly-fire bypass for " + DescribeEnemy(val2) + ".");
			}
		}

		public static bool ShouldSkipManagedPowerProjectileCollision(Projectile projectile, Collider other)
		{
			if ((Object)(object)projectile == (Object)null || (Object)(object)other == (Object)null)
			{
				return false;
			}
			GameObject gameObject = ((Component)other).gameObject;
			if ((Object)(object)gameObject == (Object)null)
			{
				return false;
			}
			GabrielPowerProjectile component = ((Component)projectile).GetComponent<GabrielPowerProjectile>();
			if ((Object)(object)component != (Object)null && IsPlayerCollider(other))
			{
				Plugin.LogDebug("Skipped managed Power projectile collision with the player.");
				return true;
			}
			if ((Object)(object)component != (Object)null && (Object)(object)ResolveManagedPowerMarker(ResolveColliderEnemy(other), gameObject) != (Object)null)
			{
				Plugin.LogDebug("Skipped managed Power projectile collision with another managed Power.");
				return true;
			}
			if (IsPlayerOwnedProjectile(projectile) && (Object)(object)ResolveManagedPowerMarker(ResolveColliderEnemy(other), gameObject) != (Object)null)
			{
				Plugin.LogDebug("Skipped player projectile collision with a managed Power.");
				return true;
			}
			return false;
		}

		public static bool ShouldSkipManagedPowerExplosionCollision(Explosion explosion, Collider other)
		{
			if ((Object)(object)explosion == (Object)null || (Object)(object)other == (Object)null || !IsPlayerCollider(other))
			{
				return false;
			}
			if (!IsManagedPowerExplosion(explosion))
			{
				return false;
			}
			Plugin.LogDebug("Skipped managed Power projectile explosion collision with the player.");
			return true;
		}

		public static void MarkEnemyProjectileDamageToManagedPower(Projectile projectile, Collider other)
		{
			if (!((Object)(object)projectile == (Object)null) && !((Object)(object)other == (Object)null) && !projectile.friendly && !projectile.playerBullet && !((Object)(object)((Component)projectile).GetComponent<GabrielPowerProjectile>() != (Object)null))
			{
				EnemyIdentifier val = ResolveColliderEnemy(other);
				if (!((Object)(object)ResolveManagedPowerMarker(val, ((Object)(object)val == (Object)null) ? null : ((Component)val).gameObject) == (Object)null))
				{
					MarkEnemyDamageToManagedPower(val);
				}
			}
		}

		public static void MarkEnemyMeleeDamageToManagedPower(EnemyIdentifier receiver, EnemyIdentifier attacker)
		{
			if (!((Object)(object)receiver == (Object)null) && !((Object)(object)attacker == (Object)null) && !((Object)(object)ResolveManagedPowerMarker(receiver, ((Component)receiver).gameObject) == (Object)null) && !EnemyFilter.IsPlayer(attacker) && !EnemyFilter.IsGabrielPower(attacker))
			{
				MarkEnemyDamageToManagedPower(receiver);
			}
		}

		public static bool ShouldSkipManagedPowerMeleeCollision(SwingCheck2 swingCheck, Collider other)
		{
			if ((Object)(object)swingCheck == (Object)null || (Object)(object)other == (Object)null)
			{
				return false;
			}
			if (!IsManagedPowerSwing(swingCheck))
			{
				return false;
			}
			if (!IsPlayerCollider(other))
			{
				if ((Object)(object)ResolveManagedPowerMarker(ResolveColliderEnemy(other), ((Component)other).gameObject) == (Object)null)
				{
					return false;
				}
				Plugin.LogDebug("Skipped managed Power melee collision with another managed Power.");
				return true;
			}
			Plugin.LogDebug("Skipped managed Power melee collision with the player.");
			return true;
		}

		public static bool ShouldSkipManagedPowerMeleeEnemyCollision(SwingCheck2 swingCheck, EnemyIdentifier receiver)
		{
			if ((Object)(object)swingCheck == (Object)null || (Object)(object)receiver == (Object)null)
			{
				return false;
			}
			if (!IsManagedPowerSwing(swingCheck))
			{
				return false;
			}
			if ((Object)(object)ResolveManagedPowerMarker(receiver, ((Component)receiver).gameObject) == (Object)null)
			{
				return false;
			}
			Plugin.LogDebug("Skipped managed Power melee damage to another managed Power.");
			return true;
		}

		public static bool ShouldBlockManagedPowerDamage(EnemyIdentifier receiver, GameObject target, GameObject sourceWeapon)
		{
			if ((Object)(object)ResolveManagedPowerMarker(receiver, target) == (Object)null)
			{
				return false;
			}
			if (IsHookDamageToManagedPower(receiver))
			{
				HandleManagedPowerHooked(ResolveHookArm(), receiver);
				return true;
			}
			if (!IsEnemyDamageToManagedPower(receiver, sourceWeapon))
			{
				Plugin.LogDebug("Blocked player/non-enemy damage against a managed Power.");
				return true;
			}
			return GabrielingsConfig.Immortal;
		}

		public static void HandleManagedPowerHooked(HookArm hookArm, EnemyIdentifier caughtEnemy)
		{
			if ((Object)(object)caughtEnemy == (Object)null)
			{
				return;
			}
			GabrielPower component = ((Component)caughtEnemy).GetComponent<GabrielPower>();
			if (!((Object)(object)component == (Object)null))
			{
				caughtEnemy.hitter = string.Empty;
				caughtEnemy.hookIgnore = false;
				caughtEnemy.hooked = false;
				if ((Object)(object)hookArm != (Object)null)
				{
					hookArm.StopThrow(1f, true);
				}
				PlayManagedPowerDodgeAnimation(component);
				ApplyProvidenceHookDodge(component);
				if (ShouldRepeatProvidenceHookDodge(caughtEnemy) && ((Behaviour)component).isActiveAndEnabled)
				{
					((MonoBehaviour)component).StartCoroutine(DelayedProvidenceHookDodge(component));
				}
				Plugin.LogDebug("Managed Power used Providence-style hook dodge.");
			}
		}

		public static bool BeginManagedPowerProjectileParry(Projectile projectile)
		{
			if ((Object)(object)projectile == (Object)null || (Object)(object)((Component)projectile).GetComponent<GabrielPowerProjectile>() == (Object)null)
			{
				return false;
			}
			_managedPowerProjectileParryDepth++;
			return true;
		}

		public static void EndManagedPowerProjectileParry()
		{
			if (_managedPowerProjectileParryDepth > 0)
			{
				_managedPowerProjectileParryDepth--;
			}
		}

		public static bool ShouldSuppressManagedPowerProjectileParryHealing(int health, bool silent)
		{
			if (_managedPowerProjectileParryDepth > 0 && !silent)
			{
				return health >= 999;
			}
			return false;
		}

		public static bool ShouldMuteManagedPowerVoice(Power power)
		{
			if (GabrielingsConfig.MutePowerVoices)
			{
				return IsManagedPower(power);
			}
			return false;
		}

		public static bool ShouldBlockManagedPowerPortalTravel(Enemy enemy)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)enemy == (Object)null || (Object)(object)((Component)enemy).GetComponent<GabrielPower>() == (Object)null)
			{
				return false;
			}
			Rigidbody component = ((Component)enemy).GetComponent<Rigidbody>();
			if ((Object)(object)component != (Object)null && !component.isKinematic)
			{
				component.velocity = Vector3.zero;
				component.angularVelocity = Vector3.zero;
			}
			Plugin.LogDebug("Blocked managed Power portal traversal.");
			return true;
		}

		public static void Tick()
		{
			if (!GabrielingsConfig.Enabled)
			{
				Reset();
				return;
			}
			if (_openAreaSignalCooldown > 0f)
			{
				_openAreaSignalCooldown -= Time.deltaTime;
			}
			ProcessPendingLockedDoorAssist();
			if (_alivePowers.Count == 0)
			{
				PruneManagedProjectiles();
				PruneEnemyDamageFrames();
				return;
			}
			HandleRepositionHotkey();
			PruneEnemyDamageFrames();
			PruneTrackedTargetsOutsidePlayerRange();
			ApplyCurrentPowerSettings();
			UpdateIdlePlayerFollowing();
			int num = CountRemainingTrackedEnemies();
			if (num != _remainingEnemySnapshot)
			{
				_remainingEnemySnapshot = num;
				Plugin.LogDebug($"Tracked enemy count changed; {num} enemies remain.");
			}
			if (num <= 0)
			{
				DespawnManagedProjectiles(silent: false);
				if (!WaitForWaveContinuation())
				{
					FinishAssist();
				}
			}
		}

		public static void DespawnAll()
		{
			DespawnAll(silent: false);
		}

		private static void DespawnAll(bool silent)
		{
			int num = 0;
			for (int i = 0; i < _alivePowers.Count; i++)
			{
				GameObject val = _alivePowers[i];
				if ((Object)(object)val != (Object)null)
				{
					CancelManagedPowerMusicRequest(val);
					Object.Destroy((Object)(object)val);
					num++;
				}
			}
			_alivePowers.Clear();
			DespawnManagedProjectiles(silent);
			if (!silent && num > 0)
			{
				Plugin.LogDebug($"Despawned {num} ally Powers.");
			}
		}

		private static bool CanAssistArena(ActivateArena arena)
		{
			if ((Object)(object)arena == (Object)null || arena.activated || arena.forEnemy)
			{
				return false;
			}
			if (HasConfiguredEnemies(arena))
			{
				return true;
			}
			return HasDoor(arena);
		}

		private static bool HasDoor(ActivateArena arena)
		{
			Door[] doors = arena.doors;
			if (doors == null || doors.Length == 0)
			{
				return false;
			}
			bool flag = false;
			for (int i = 0; i < doors.Length; i++)
			{
				if ((Object)(object)doors[i] != (Object)null)
				{
					flag = true;
					break;
				}
			}
			if (!flag)
			{
				return false;
			}
			return true;
		}

		private static bool HasActiveState()
		{
			if (_alivePowers.Count <= 0 && _trackedEnemies.Count <= 0 && !((Object)(object)_pendingLockedDoor != (Object)null))
			{
				return _pendingOpenAreaScan;
			}
			return true;
		}

		private static bool HasConfiguredEnemies(ActivateArena arena)
		{
			GameObject[] enemies = arena.enemies;
			if (enemies == null || enemies.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < enemies.Length; i++)
			{
				if ((Object)(object)enemies[i] != (Object)null)
				{
					return true;
				}
			}
			return false;
		}

		private static void ScheduleLockedDoorAssist(Door door, string reason)
		{
			if ((Object)(object)door == (Object)null)
			{
				Plugin.LogDebug("Locked-door assist was not scheduled from " + reason + ": door is null.");
				return;
			}
			if (_alivePowers.Count > 0 || _trackedEnemies.Count > 0)
			{
				Plugin.LogDebug("Locked-door assist from " + reason + " ignored because an assist is already active.");
				return;
			}
			if ((Object)(object)_pendingLockedDoor != (Object)null || _pendingOpenAreaScan)
			{
				Plugin.LogDebug("Locked-door assist from " + reason + " ignored because a door scan is already pending.");
				return;
			}
			_pendingLockedDoor = door;
			_pendingOpenAreaScan = false;
			_pendingLockedDoorTimer = 0.25f;
			_pendingLockedDoorTimeout = 8f;
			Plugin.LogDebug($"Locked-door assist scheduled from {reason}; scanning for enemies for up to {8f:0.0}s.");
		}

		private static void ScheduleOpenAreaAssist(string reason)
		{
			if (!GabrielingsConfig.ExtendedEnemyCheck)
			{
				Plugin.LogDebug("Extended enemy check from " + reason + " ignored because fallback scans are disabled.");
				return;
			}
			if (_alivePowers.Count > 0 || _trackedEnemies.Count > 0)
			{
				Plugin.LogDebug("Open-area assist from " + reason + " ignored because an assist is already active.");
				return;
			}
			if ((Object)(object)_pendingLockedDoor != (Object)null || _pendingOpenAreaScan)
			{
				Plugin.LogDebug("Open-area assist from " + reason + " ignored because a scan is already pending.");
				return;
			}
			_pendingLockedDoor = null;
			_pendingOpenAreaScan = true;
			_pendingLockedDoorTimer = 0.25f;
			_pendingLockedDoorTimeout = 8f;
			Plugin.LogDebug($"Extended enemy check scheduled from {reason}; scanning for enemies for up to {8f:0.0}s.");
		}

		private static void ProcessPendingLockedDoorAssist()
		{
			if ((Object)(object)_pendingLockedDoor == (Object)null && !_pendingOpenAreaScan)
			{
				return;
			}
			_pendingLockedDoorTimeout -= Time.deltaTime;
			if (_pendingLockedDoorTimeout <= 0f)
			{
				Plugin.LogDebug("Fallback scan timed out without finding active enemies.");
				ClearPendingLockedDoorAssist();
				return;
			}
			_pendingLockedDoorTimer -= Time.deltaTime;
			if (!(_pendingLockedDoorTimer > 0f))
			{
				if ((Object)(object)_pendingLockedDoor != (Object)null && !_pendingLockedDoor.locked)
				{
					Plugin.LogDebug("Locked-door fallback scan skipped because the door is no longer locked.");
					ClearPendingLockedDoorAssist();
				}
				else if (!TryStartAssistFromCurrentEnemies("locked-door fallback scan"))
				{
					_pendingLockedDoorTimer = 0.5f;
					Plugin.LogDebug($"Fallback scan found no active enemies; retrying for {_pendingLockedDoorTimeout:0.0}s.");
				}
			}
		}

		private static void ClearPendingLockedDoorAssist()
		{
			_pendingLockedDoor = null;
			_pendingOpenAreaScan = false;
			_pendingLockedDoorTimer = 0f;
			_pendingLockedDoorTimeout = 0f;
		}

		private static bool TryStartAssistFromCurrentEnemies(string reason)
		{
			bool pendingOpenAreaScan = _pendingOpenAreaScan;
			_trackedArena = null;
			_trackedEnemies.Clear();
			CollectCurrentEnemyTargets(_trackedEnemies, _pendingOpenAreaScan);
			_remainingEnemySnapshot = CountRemainingTrackedEnemies();
			if (_remainingEnemySnapshot <= 0)
			{
				_trackedEnemies.Clear();
				return false;
			}
			ClearPendingLockedDoorAssist();
			_targetByPlayerProximity = pendingOpenAreaScan;
			Plugin.LogDebug($"{reason} accepted with {_remainingEnemySnapshot} tracked active enemies.");
			_clearGraceTimer = 0f;
			SpawnPowers(GabrielingsConfig.PowerCount);
			return true;
		}

		private static Door FindFirstDoor(ActivateArena arena)
		{
			if ((Object)(object)arena == (Object)null || arena.doors == null)
			{
				return null;
			}
			Door[] doors = arena.doors;
			for (int i = 0; i < doors.Length; i++)
			{
				if ((Object)(object)doors[i] != (Object)null)
				{
					return doors[i];
				}
			}
			return null;
		}

		private static void CollectArenaTargets(ActivateArena arena, List<EnemyIdentifier> targets)
		{
			targets.Clear();
			GameObject[] enemies = arena.enemies;
			if (enemies == null || enemies.Length == 0)
			{
				return;
			}
			foreach (GameObject val in enemies)
			{
				if (!((Object)(object)val == (Object)null))
				{
					EnemyIdentifier val2 = val.GetComponent<EnemyIdentifier>();
					if ((Object)(object)val2 == (Object)null)
					{
						val2 = val.GetComponentInChildren<EnemyIdentifier>(true);
					}
					if (IsValidAssistTarget(val2) && !targets.Contains(val2))
					{
						targets.Add(val2);
					}
				}
			}
		}

		private static void CollectCurrentEnemyTargets(List<EnemyIdentifier> targets, bool requireCombatSignal)
		{
			targets.Clear();
			List<EnemyIdentifier> list = null;
			try
			{
				EnemyTracker instance = MonoSingleton<EnemyTracker>.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					list = instance.GetCurrentEnemies();
				}
			}
			catch
			{
				list = null;
			}
			if (list != null && list.Count > 0)
			{
				for (int i = 0; i < list.Count; i++)
				{
					AddCurrentTarget(list[i], targets, requireCombatSignal);
				}
				if (targets.Count > 0)
				{
					Plugin.LogDebug($"EnemyTracker provided {targets.Count} valid active targets.");
					return;
				}
			}
			EnemyIdentifier[] array = Resources.FindObjectsOfTypeAll<EnemyIdentifier>();
			for (int j = 0; j < array.Length; j++)
			{
				AddCurrentTarget(array[j], targets, requireCombatSignal);
			}
			Plugin.LogDebug($"Resource scan provided {targets.Count} valid active targets.");
		}

		private static void AddCurrentTarget(EnemyIdentifier eid, List<EnemyIdentifier> targets, bool requireCombatSignal)
		{
			if (IsValidAssistTarget(eid) && !targets.Contains(eid))
			{
				GameObject gameObject = ((Component)eid).gameObject;
				if (!((Object)(object)gameObject == (Object)null) && gameObject.activeInHierarchy && (!requireCombatSignal || IsOpenAreaCombatTarget(eid)))
				{
					targets.Add(eid);
				}
			}
		}

		private static bool IsOpenAreaCombatTarget(EnemyIdentifier eid)
		{
			if (!IsValidActiveTarget(eid))
			{
				return false;
			}
			if (eid.target != null && eid.target.isPlayer)
			{
				return IsTargetCloseToPlayer(eid);
			}
			return false;
		}

		private static bool IsValidActiveTarget(EnemyIdentifier eid)
		{
			if (!IsValidAssistTarget(eid))
			{
				return false;
			}
			GameObject gameObject = ((Component)eid).gameObject;
			if ((Object)(object)gameObject != (Object)null)
			{
				return gameObject.activeInHierarchy;
			}
			return false;
		}

		private static bool IsValidAssistTarget(EnemyIdentifier eid)
		{
			if (!EnemyFilter.IsArenaTarget(eid))
			{
				return false;
			}
			if (!GabrielingsConfig.AssistBosses && IsBossTarget(eid))
			{
				return false;
			}
			return true;
		}

		private static bool IsBossTarget(EnemyIdentifier eid)
		{
			if ((Object)(object)eid == (Object)null)
			{
				return false;
			}
			if (eid.isBoss)
			{
				return true;
			}
			if (!((Object)(object)((Component)eid).GetComponent<BossHealthBar>() != (Object)null))
			{
				return (Object)(object)((Component)eid).GetComponent<BossIdentifier>() != (Object)null;
			}
			return true;
		}

		private static bool IsEarthmoverFakeBossBar(BossHealthBar bossBar)
		{
			if ((Object)(object)bossBar == (Object)null)
			{
				return false;
			}
			if (IsEarthmoverLevel())
			{
				return true;
			}
			if (ContainsEarthmoverText(bossBar.bossName) || ContainsEarthmoverText(((Object)((Component)bossBar).gameObject).name))
			{
				return true;
			}
			IEnemyHealthDetails source = bossBar.source;
			if (source != null && ContainsEarthmoverText(source.FullName))
			{
				return true;
			}
			Transform val = ((Component)bossBar).transform;
			while ((Object)(object)val != (Object)null)
			{
				if (ContainsEarthmoverText(((Object)val).name))
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static bool IsEarthmoverLevel()
		{
			//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)
			try
			{
				StatsManager instance = MonoSingleton<StatsManager>.Instance;
				if ((Object)(object)instance != (Object)null && instance.levelNumber == 29)
				{
					return true;
				}
			}
			catch
			{
			}
			try
			{
				if (SceneHelper.CurrentLevelNumber == 29)
				{
					return true;
				}
			}
			catch
			{
			}
			if (ContainsEarthmoverText(SceneHelper.CurrentScene))
			{
				return true;
			}
			try
			{
				Scene activeScene = SceneManager.GetActiveScene();
				return ContainsEarthmoverText(((Scene)(ref activeScene)).name);
			}
			catch
			{
				return false;
			}
		}

		private static bool ContainsEarthmoverText(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			if (value.IndexOf("7-4", StringComparison.OrdinalIgnoreCase) < 0 && value.IndexOf("Earthmover", StringComparison.OrdinalIgnoreCase) < 0 && value.IndexOf("Earth Mover", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return value.IndexOf("1000-THR", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static EnemyIdentifier ResolveBossEnemy(BossHealthBar bossBar)
		{
			if ((Object)(object)bossBar == (Object)null)
			{
				return null;
			}
			EnemyIdentifier component = ((Component)bossBar).GetComponent<EnemyIdentifier>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			IEnemyHealthDetails source = bossBar.source;
			EnemyIdentifier val = (EnemyIdentifier)(object)((source is EnemyIdentifier) ? source : null);
			if (val != null)
			{
				return val;
			}
			component = ((Component)bossBar).GetComponentInParent<EnemyIdentifier>();
			if ((Object)(object)component != (Object)null)
			{
				return component;
			}
			return ((Component)bossBar).GetComponentInChildren<EnemyIdentifier>(true);
		}

		private static string DescribeEnemy(EnemyIdentifier eid)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)eid == (Object)null)
			{
				return "<null>";
			}
			GameObject gameObject = ((Component)eid).gameObject;
			string arg = (((Object)(object)gameObject == (Object)null) ? "<no GameObject>" : ((Object)gameObject).name);
			return $"{arg} ({eid.enemyType})";
		}

		private static void SpawnPowers(int count)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ResolveSpawnOrigin(_trackedArena);
			GameObject val2 = PowerPrefabExtractor.ResolvePrefab();
			if ((Object)(object)val2 == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"Gabrielings: Power prefab could not be resolved.");
				}
				_trackedEnemies.Clear();
				_trackedArena = null;
				return;
			}
			count = Mathf.Clamp(count, 1, 100);
			int num = 0;
			Vector3 val3 = default(Vector3);
			for (int i = 0; i < count; i++)
			{
				((Vector3)(ref val3))..ctor(Random.Range(-1.5f, 1.5f), 0f, Random.Range(-1.5f, 1.5f));
				GameObject val4;
				try
				{
					val4 = Object.Instantiate<GameObject>(val2, val + val3, Quaternion.identity);
				}
				catch (Exception ex)
				{
					Plugin.LogDebug("Power instantiate failed: " + ex.GetType().Name + ": " + ex.Message);
					continue;
				}
				if (!((Object)(object)val4 == (Object)null))
				{
					ConfigureSpawnedPower(val4, num);
					_alivePowers.Add(val4);
					num++;
				}
			}
			if (num <= 0)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)"Gabrielings: Power prefab resolved, but no Powers could be spawned.");
				}
				_trackedEnemies.Clear();
				_trackedArena = null;
			}
			else
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)$"Gabrielings: spawned {num} Powers.");
				}
			}
		}

		private static void ConfigureSpawnedPower(GameObject go, int followIndex)
		{
			GabrielPower gabrielPower = go.GetComponent<GabrielPower>();
			if ((Object)(object)gabrielPower == (Object)null)
			{
				gabrielPower = go.AddComponent<GabrielPower>();
			}
			gabrielPower.EnemyIdentifier = go.GetComponent<EnemyIdentifier>();
			gabrielPower.Power = go.GetComponent<Power>();
			gabrielPower.VoiceAudio = go.GetComponent<AudioSource>();
			gabrielPower.Animator = go.GetComponent<Animator>();
			gabrielPower.FollowIndex = followIndex;
			gabrielPower.FollowPhase = Random.Range(0f, (float)Math.PI * 2f);
			if ((Object)(object)gabrielPower.EnemyIdentifier != (Object)null)
			{
				gabrielPower.BaseHealth = gabrielPower.EnemyIdentifier.health;
			}
			EnemyIdentifier enemyIdentifier = gabrielPower.EnemyIdentifier;
			if ((Object)(object)enemyIdentifier != (Object)null)
			{
				enemyIdentifier.ignorePlayer = true;
				enemyIdentifier.attackEnemies = true;
				enemyIdentifier.immuneToFriendlyFire = false;
				enemyIdentifier.hookIgnore = false;
				enemyIdentifier.prioritizePlayerOverFallback = false;
				enemyIdentifier.prioritizeEnemiesUnlessAttacked = false;
				enemyIdentifier.ResetTarget();
				enemyIdentifier.blessed = false;
				if (GabrielingsConfig.Immortal)
				{
					enemyIdentifier.health = float.MaxValue;
				}
				Enemy component = go.GetComponent<Enemy>();
				if ((Object)(object)component != (Object)null && component.vision != null)
				{
					component.SyncVision();
				}
				RefreshPowerCombatTarget(gabrielPower, enemyIdentifier);
			}
			RefreshManagedPowerPlayerCollision(gabrielPower, force: true);
			if ((Object)(object)gabrielPower.Power != (Object)null)
			{
				gabrielPower.Power.aggroBounds = null;
			}
			DetachFromPowerCooldowns(gabrielPower.Power);
			if (!go.activeSelf)
			{
				go.SetActive(true);
			}
			ApplyManagedPowerAudioSettings(gabrielPower);
			CancelManagedPowerMusicRequest(gabrielPower, decrementMusicRequest: false);
			RemoveManagedPowerPortalTraveller(gabrielPower);
		}

		private static void ConfigureSwingChecks(GameObject go, EnemyIdentifier eid, EnemyIdentifier target)
		{
			//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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			SwingCheck2[] componentsInChildren = go.GetComponentsInChildren<SwingCheck2>(true);
			EnemyType type = ResolveMeleeAttackerType(eid, target);
			int num = ((!IsFleshBossTarget(target)) ? 1 : 4);
			foreach (SwingCheck2 val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.OverrideEnemyIdentifier(eid);
					val.type = type;
					if (val.enemyDamage <= 0 && val.damage > 0)
					{
						val.enemyDamage = Mathf.Max(num, val.damage / 10);
					}
					else if (val.enemyDamage > 0 && val.enemyDamage < num)
					{
						val.enemyDamage = num;
					}
				}
			}
			Plugin.LogDebug($"Configured {componentsInChildren.Length} Power melee hitboxes.");
		}

		private static EnemyType ResolveMeleeAttackerType(EnemyIdentifier owner, EnemyIdentifier target)
		{
			if (!((Object)(object)owner != (Object)null))
			{
				return (EnemyType)40;
			}
			return (EnemyType)37;
		}

		private static Vector3 ResolveSpawnOrigin(ActivateArena arena)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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)
			NewMovement instance = MonoSingleton<NewMovement>.Instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)((Component)instance).transform != (Object)null)
			{
				return ((Component)instance).transform.position + Vector3.up * 1.5f;
			}
			if ((Object)(object)arena == (Object)null || (Object)(object)((Component)arena).transform == (Object)null)
			{
				return Vector3.zero;
			}
			return ((Component)arena).transform.position + Vector3.up * 1.5f;
		}

		private static void ApplyCurrentPowerSettings()
		{
			bool immortal = GabrielingsConfig.Immortal;
			for (int num = _alivePowers.Count - 1; num >= 0; num--)
			{
				GameObject val = _alivePowers[num];
				if ((Object)(object)val == (Object)null)
				{
					_alivePowers.RemoveAt(num);
				}
				else
				{
					GabrielPower component = val.GetComponent<GabrielPower>();
					if (!((Object)(object)component == (Object)null))
					{
						EnemyIdentifier val2 = (((Object)(object)component.EnemyIdentifier != (Object)null) ? component.EnemyIdentifier : val.GetComponent<EnemyIdentifier>());
						if (!((Object)(object)val2 == (Object)null))
						{
							component.EnemyIdentifier = val2;
							if ((Object)(object)component.Power == (Object)null)
							{
								component.Power = val.GetComponent<Power>();
							}
							if ((Object)(object)component.Animator == (Object)null)
							{
								component.Animator = val.GetComponent<Animator>();
							}
							val2.ignorePlayer = true;
							val2.attackEnemies = true;
							val2.immuneToFriendlyFire = false;
							val2.hookIgnore = false;
							val2.prioritizePlayerOverFallback = false;
							val2.prioritizeEnemiesUnlessAttacked = false;
							DetachFromPowerCooldowns(component.Power);
							RefreshPowerCombatTarget(component, val2);
							RefreshManagedPowerPlayerCollision(component, force: false);
							ApplyManagedPowerAudioSettings(component);
							CancelManagedPowerMusicRequest(component);
							RemoveManagedPowerPortalTraveller(component);
							val2.blessed = false;
							if (immortal)
							{
								val2.health = float.MaxValue;
							}
							else if (component.BaseHealth > 0f && val2.health > component.BaseHealth)
							{
								val2.health = component.BaseHealth;
							}
						}
					}
				}
			}
		}

		private static void ApplyManagedPowerAudioSettings(GabrielPower marker)
		{
			if (!((Object)(object)marker == (Object)null) && GabrielingsConfig.MutePowerVoices)
			{
				if ((Object)(object)marker.VoiceAudio == (Object)null)
				{
					marker.VoiceAudio = ((Component)marker).GetComponent<AudioSource>();
				}
				if ((Object)(object)marker.VoiceAudio != (Object)null && marker.VoiceAudio.isPlaying)
				{
					marker.VoiceAudio.Stop();
				}
			}
		}

		private static void CancelManagedPowerMusicRequest(GameObject go, bool decrementMusicRequest = true)
		{
			if (!((Object)(object)go == (Object)null))
			{
				CancelManagedPowerMusicRequest(go.GetComponent<GabrielPower>(), decrementMusicRequest);
			}
		}

		private static void CancelManagedPowerMusicRequest(GabrielPower marker, bool decrementMusicRequest = true)
		{
			if ((Object)(object)marker == (Object)null || (Object)(object)((Component)marker).gameObject == (Object)null)
			{
				return;
			}
			Enemy component = ((Component)marker).GetComponent<Enemy>();
			if ((Object)(object)component == (Object)null || !component.musicRequested)
			{
				return;
			}
			component.musicRequested = false;
			if (decrementMusicRequest)
			{
				try
				{
					MusicManager val = default(MusicManager);
					if (MonoSingleton<MusicManager>.TryGetInstance(ref val) && (Object)(object)val != (Object)null)
					{
						val.PlayCleanMusic();
					}
				}
				catch
				{
				}
			}
			Plugin.LogDebug("Cancelled managed Power combat music request.");
		}

		private static void RemoveManagedPowerPortalTraveller(GabrielPower marker)
		{
			if ((Object)(object)marker == (Object)null || (Object)(object)((Component)marker).gameObject == (Object)null)
			{
				return;
			}
			Enemy component = ((Component)marker).GetComponent<Enemy>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			try
			{
				PortalManagerV2 val = default(PortalManagerV2);
				if (MonoSingleton<PortalManagerV2>.TryGetInstance(ref val) && (Object)(object)val != (Object)null)
				{
					val.RemoveTraveller((IPortalTraveller)(object)component);
				}
			}
			catch
			{
			}
		}

		private static int CountRemainingTrackedEnemies()
		{
			int num = 0;
			for (int num2 = _trackedEnemies.Count - 1; num2 >= 0; num2--)
			{
				EnemyIdentifier val = _trackedEnemies[num2];
				if ((Object)(object)val == (Object)null)
				{
					_trackedEnemies.RemoveAt(num2);
				}
				else if (EnemyFilter.IsArenaTarget(val))
				{
					num++;
				}
			}
			return num;
		}

		private static void RefreshPowerCombatTarget(GabrielPower marker, EnemyIdentifier eid)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			if ((Object)(object)marker == (Object)null || (Object)(object)eid == (Object)null)
			{
				return;
			}
			EnemyIdentifier val = SelectPowerTarget(((Component)eid).transform.position, marker.CurrentTarget);
			if ((Object)(object)val == (Object)null)
			{
				if ((Object)(object)marker.CurrentTarget != (Object)null)
				{
					marker.CurrentTarget = null;
					eid.ResetTarget();
					ConfigureSwingChecks(((Component)eid).gameObject, eid, null);
				}
				return;
			}
			bool num = (Object)(object)marker.CurrentTarget != (Object)(object)val || eid.target == null || !eid.target.isEnemy || (Object)(object)eid.target.enemyIdentifier != (Object)(object)val;
			marker.CurrentTarget = val;
			if (num)
			{
				eid.target = new EnemyTarget(val);
				ConfigureSwingChecks(((Component)eid).gameObject, eid, val);
				Plugin.LogDebug("Power target set to " + DescribeEnemy(val) + ".");
			}
		}

		private static EnemyIdentifier SelectPowerTarget(Vector3 origin, EnemyIdentifier preferred)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			if (IsSelectablePowerTarget(preferred))
			{
				return preferred;
			}
			EnemyIdentifier result = null;
			float num = float.MaxValue;
			Vector3 position = Vector3.zero;
			bool flag = _targetByPlayerProximity && TryGetPlayerPosition(out position);
			for (int num2 = _trackedEnemies.Count - 1; num2 >= 0; num2--)
			{
				EnemyIdentifier val = _trackedEnemies[num2];
				if (IsSelectablePowerTarget(val))
				{
					Vector3 val2 = (flag ? position : origin);
					Vector3 val3 = ((Component)val).transform.position - val2;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = val;
					}
				}
			}
			return result;
		}

		private static bool IsSelectablePowerTarget(EnemyIdentifier target)
		{
			if (!IsValidActiveTarget(target))
			{
				return false;
			}
			if (_targetByPlayerProximity)
			{
				return IsTargetCloseToPlayer(target);
			}
			return true;
		}

		private static bool IsManagedPowerTarget(EnemyIdentifier target)
		{
			if (!IsValidActiveTarget(target) || !_trackedEnemies.Contains(target))
			{
				return false;
			}
			for (int i = 0; i < _alivePowers.Count; i++)
			{
				GameObject val = _alivePowers[i];
				if (!((Object)(object)val == (Object)null))
				{
					GabrielPower component = val.GetComponent<GabrielPower>();
					if ((Object)(object)component != (Object)null && (Object)(object)component.CurrentTarget == (Object)(object)target)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static GabrielPower FindNearestManagedPower(Vector3 position, float maxDistance)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			GabrielPower result = null;
			float num = maxDistance * maxDistance;
			for (int i = 0; i < _alivePowers.Count; i++)
			{
				GameObject val = _alivePowers[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				GabrielPower component = val.GetComponent<GabrielPower>();
				if (!((Object)(object)component == (Object)null))
				{
					Vector3 val2 = val.transform.position - position;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						result = component;
					}
				}
			}
			return result;
		}

		private static TargetHandle CreateTargetHandle(EnemyIdentifier target)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			if ((Object)(object)target == (Object)null)
			{
				return null;
			}
			Enemy component = ((Component)target).GetComponent<Enemy>();
			if (!((Object)(object)component == (Object)null))
			{
				return new TargetHandle((ITarget)(object)component);
			}
			return null;
		}

		private static void TrackManagedProjectile(Projectile projectile)
		{
			if (!((Object)(object)projectile == (Object)null) && !((Object)(object)((Component)projectile).gameObject == (Object)null))
			{
				GameObject gameObject = ((Component)projectile).gameObject;
				if (!_managedProjectiles.Contains(gameObject))
				{
					_managedProjectiles.Add(gameObject);
				}
			}
		}

		private static void DestroyManagedProjectile(Projectile projectile)
		{
			if (!((Object)(object)projectile == (Object)null) && !((Object)(object)((Component)projectile).gameObject == (Object)null))
			{
				GameObject gameObject = ((Component)projectile).gameObject;
				_managedProjectiles.Remove(gameObject);
				Object.Destroy((Object)(object)gameObject);
			}
		}

		private static void DespawnManagedProjectiles(bool silent)
		{
			int num = 0;
			for (int num2 = _managedProjectiles.Count - 1; num2 >= 0; num2--)
			{
				GameObject val = _managedProjectiles[num2];
				if (!((Object)(object)val == (Object)null))
				{
					Object.Destroy((Object)(object)val);
					num++;
				}
			}
			_managedProjectiles.Clear();
			if (!silent && num > 0)
			{
				Plugin.LogDebug($"Despawned {num} managed Power projectiles.");
			}
		}

		private static void PruneManagedProjectiles()
		{
			for (int num = _managedProjectiles.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)_managedProjectiles[num] == (Object)null)
				{
					_managedProjectiles.RemoveAt(num);
				}
			}
		}

		private static void MarkEnemyDamageToManagedPower(EnemyIdentifier receiver)
		{
			if (!((Object)(object)receiver == (Object)null))
			{
				_enemyDamageFrames[receiver] = Time.frameCount;
			}
		}

		private static bool IsEnemyDamageToManagedPower(EnemyIdentifier receiver, GameObject sourceWeapon)
		{
			if ((Object)(object)sourceWeapon != (Object)null)
			{
				if ((Object)(object)sourceWeapon.GetComponentInParent<GabrielPower>() != (Object)null || (Object)(object)sourceWeapon.GetComponentInParent<GabrielPowerProjectile>() != (Object)null)
				{
					return false;
				}
				if ((Object)(object)sourceWeapon.GetComponentInParent<NewMovement>() != (Object)null)
				{
					return false;
				}
				EnemyIdentifier componentInParent = sourceWeapon.GetComponentInParent<EnemyIdentifier>();
				if ((Object)(object)componentInParent != (Object)null)
				{
					if (!EnemyFilter.IsPlayer(componentInParent))
					{
						return !EnemyFilter.IsGabrielPower(componentInParent);
					}
					return false;
				}
			}
			if ((Object)(object)receiver != (Object)null && _enemyDamageFrames.TryGetValue(receiver, out var value) && Time.frameCount - value <= 1)
			{
				return true;
			}
			if ((Object)(object)receiver != (Object)null)
			{
				return receiver.hitter == "enemy";
			}
			return false;
		}

		private static bool IsManagedPowerExplosion(Explosion explosion)
		{
			if ((Object)(object)explosion == (Object)null)
			{
				return false;
			}
			if (EnemyFilter.IsGabrielPower(explosion.originEnemy))
			{
				return true;
			}
			GameObject sourceWeapon = explosion.sourceWeapon;
			if ((Object)(object)sourceWeapon != (Object)null)
			{
				if (!((Object)(object)sourceWeapon.GetComponentInParent<GabrielPower>() != (Object)null))
				{
					return (Object)(object)sourceWeapon.GetComponentInParent<GabrielPowerProjectile>() != (Object)null;
				}
				return true;
			}
			return false;
		}

		private static bool IsPlayerOwnedProjectile(Projectile projectile)
		{
			if ((Object)(object)projectile == (Object)null)
			{
				return false;
			}
			if (projectile.playerBullet || projectile.friendly)
			{
				return true;
			}
			GameObject sourceWeapon = projectile.sourceWeapon;
			if ((Object)(object)sourceWeapon == (Object)null)
			{
				return false;
			}
			if ((Object)(object)sourceWeapon.GetComponentInParent<NewMovement>() != (Object)null)
			{
				return true;
			}
			return EnemyFilter.IsPlayer(sourceWeapon.GetComponentInParent<EnemyIdentifier>());
		}

		private static bool IsHookDamageToManagedPower(EnemyIdentifier receiver)
		{
			if ((Object)(object)receiver != (Object)null)
			{
				return receiver.hitter == "hook";
			}
			return false;
		}

		private static HookArm ResolveHookArm()
		{
			try
			{
				return MonoSingleton<HookArm>.Instance;
			}
			catch
			{
				return null;
			}
		}

		private static void PruneEnemyDamageFrames()
		{
			if (_enemyDamageFrames.Count == 0)
			{
				return;
			}
			List<EnemyIdentifier> list = null;
			foreach (KeyValuePair<EnemyIdentifier, int> enemyDamageFrame in _enemyDamageFrames)
			{
				if ((Object)(object)enemyDamageFrame.Key == (Object)null || Time.frameCount - enemyDamageFrame.Value > 1)
				{
					if (list == null)
					{
						list = new List<EnemyIdentifier>();
					}
					list.Add(enemyDamageFrame.Key);
				}
			}
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					_enemyDamageFrames.Remove(list[i]);
				}
			}
		}

		public static bool TryHandleManagedPowerFleshBossMeleeCollision(SwingCheck2 swingCheck, EnemyIdentifier receiver, Collider other, EnemyIdentifier attacker)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)swingCheck == (Object)null || (Object)(object)receiver == (Object)null || (Object)(object)other == (Object)null)
			{
				return false;
			}
			if (!IsManagedPowerSwing(swingCheck) || !IsFleshBossTarget(receiver) || !IsSelectablePowerTarget(receiver))
			{
				return false;
			}
			if (HasManagedMeleeHit(swingCheck, receiver))
			{
				return true;
			}
			RecordManagedMeleeHit(swingCheck, receiver);
			if (!swingCheck.hitColliders.Contains(other))
			{
				swingCheck.hitColliders.Add(other);
			}
			if (swingCheck.enemyDamage <= 0 && swingCheck.damage > 0)
			{
				swingCheck.enemyDamage = Mathf.Max(4, swingCheck.damage / 10);
			}
			receiver.hitter = "enemy";
			float num = Mathf.Max(1f, (float)swingCheck.enemyDamage);
			if ((Object)(object)attacker != (Object)null)
			{
				num *= attacker.totalDamageModifier;
			}
			Vector3 val = ((Component)swingCheck).transform.position - ((Component)other).transform.position;
			Vector3 val2 = (((Vector3)(ref val)).normalized + Vector3.up) * 10000f;
			receiver.DeliverDamage(((Component)other).gameObject, val2, ((Component)other).transform.position, num, false, 0f, (GameObject)null, false, false);
			Plugin.LogDebug("Applied managed Power melee damage to Flesh boss target " + DescribeEnemy(receiver) + ".");
			return true;
		}

		public static void ClearManagedPowerMeleeHitRecord(SwingCheck2 swingCheck)
		{
			if ((Object)(object)swingCheck != (Object)null)
			{
				_managedMeleeHitEnemies.Remove(swingCheck);
			}
		}

		private static bool HasManagedMeleeHit(SwingCheck2 swingCheck, EnemyIdentifier receiver)
		{
			if ((Object)(object)swingCheck != (Object)null && (Object)(object)receiver != (Object)null && _managedMeleeHitEnemies.TryGetValue(swingCheck, out var value))
			{
				return value.Contains(receiver);
			}
			return false;
		}

		private static void RecordManagedMeleeHit(SwingCheck2 swingCheck, EnemyIdentifier receiver)
		{
			if (!((Object)(object)swingCheck == (Object)null) && !((Object)(object)receiver == (Object)null))
			{
				if (!_managedMeleeHitEnemies.TryGetValue(swingCheck, out var value))
				{
					value = new List<EnemyIdentifier>(2);
					_managedMeleeHitEnemies.Add(swingCheck, value);
				}
				if (!value.Contains(receiver))
				{
					value.Add(receiver);
				}
			}
		}

		private static GabrielPower ResolveManagedPowerMarker(EnemyIdentifier receiver, GameObject target)
		{
			GabrielPower result = default(GabrielPower);
			if ((Object)(object)receiver != (Object)null && ((Component)receiver).TryGetComponent<GabrielPower>(ref result))
			{
				return result;
			}
			if (!((Object)(object)target == (Object)null))
			{
				return target.GetComponentInParent<GabrielPower>();
			}
			return null;
		}

		private static bool IsManagedPowerSwing(SwingCheck2 swingCheck)
		{
			if ((Object)(object)swingCheck == (Object)null)
			{
				return false;
			}
			if ((Object)(object)swingCheck.eid != (Object)null && (Object)(object)((Component)swingCheck.eid).GetComponentInParent<GabrielPower>() != (Object)null)
			{
				return true;
			}
			return (Object)(object)((Component)swingCheck).GetComponentInParent<GabrielPower>() != (Object)null;
		}

		private static bool IsFleshBossTarget(EnemyIdentifier target)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			if ((Object)(object)target != (Object)null)
			{
				if ((int)target.enemyType != 17)
				{
					return (int)target.enemyType == 30;
				}
				return true;
			}
			return false;
		}

		private static bool IsPlayerCollider(Collider other)
		{
			if ((Object)(object)other == (Object)null || (Object)(object)((Component)other).gameObject == (Object)null)
			{
				return false;
			}
			if (!((Component)other).gameObject.CompareTag("Player"))
			{
				return (Object)(object)((Component)other).GetComponentInParent<NewMovement>() != (Object)null;
			}
			return true;
		}

		private static void RefreshManagedPowerPlayerCollision(GabrielPower marker, bool force)
		{
			if ((Object)(object)marker == (Object)null || (Object)(object)((Component)marker).gameObject == (Object)null || (!force && Time.time < marker.NextPlayerCollisionRefreshTime))
			{
				return;
			}
			Collider[] array = ResolvePlayerColliders();
			if (array.Length == 0)
			{
				marker.NextPlayerCollisionRefreshTime = Time.time + 0.5f;
				return;
			}
			if (force || marker.Colliders == null || marker.Colliders.Length == 0 || !HasSameColliders(marker.IgnoredPlayerColliders, array))
			{
				marker.Colliders = ((Component)marker).GetComponentsInChildren<Collider>(true);
				marker.IgnoredPlayerColliders = array;
			}
			Collider[] colliders = marker.Colliders;
			foreach (Collider val in colliders)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				foreach (Collider val2 in array)
				{
					if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val == (Object)(object)val2))
					{
						Physics.IgnoreCollision(val, val2, true);
					}
				}
			}
			marker.NextPlayerCollisionRefreshTime = Time.time + 0.5f;
		}

		private static Collider[] ResolvePlayerColliders()
		{
			NewMovement instance = MonoSingleton<NewMovement>.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return EmptyColliders;
			}
			Collider[] componentsInChildren = ((Component)instance).GetComponentsInChildren<Collider>(true);
			if (componentsInChildren != null && componentsInChildren.Length != 0)
			{
				return componentsInChildren;
			}
			if ((Object)(object)instance.playerCollider != (Object)null)
			{
				return (Collider[])(object)new CapsuleCollider[1] { instance.playerCollider };
			}
			Collider component = ((Component)instance).GetComponent<Collider>();
			if (!((Object)(object)component == (Object)null))
			{
				return (Collider[])(object)new Collider[1] { component };
			}
			return EmptyColliders;
		}

		private static bool HasSameColliders(Collider[] existing, Collider[] current)
		{
			if (existing == null || current == null || existing.Length != current.Length)
			{
				return false;
			}
			for (int i = 0; i < existing.Length; i++)
			{
				if ((Object)(object)existing[i] != (Object)(object)current[i])
				{
					return false;
				}
			}
			return true;
		}

		private static void HandleRepositionHotkey()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			KeyCode repositionKey = GabrielingsConfig.RepositionKey;
			if ((int)repositionKey != 0 && Input.GetKeyDown(repositionKey))
			{
				RepositionPowersToPlayer("keybind");
			}
		}

		private static void RepositionPowersToPlayer(string reason)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_0053: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			NewMovement instance = MonoSingleton<NewMovement>.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)((Component)instance).transform == (Object)null)
			{
				return;
			}
			int num = 0;
			for (int i = 0; i < _alivePowers.Count; i++)
			{
				GameObject val = _alivePowers[i];
				if (!((Object)(object)val == (Object)null))
				{
					GabrielPower component = val.GetComponent<GabrielPower>();
					Vector3 position = (((Object)(object)component == (Object)null) ? (((Component)instance).transform.position + Vector3.up * 2f) : CalculateFollowPosition(component, ((Component)instance).transform));
					MovePowerInstantly(val, position);
					num++;
				}
			}
			if (num > 0)
			{
				Plugin.LogDebug($"Repositioned {num} Powers near V1 from {reason}.");
			}
		}

		private static void ApplyProvidenceHookDodge(GabrielPower marker)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_006f: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)marker == (Object)null) && !((Object)(object)((Component)marker).gameObject == (Object)null))
			{
				Transform transform = ((Component)marker).transform;
				Vector3 val = transform.up * Random.Range(-5f, 5f) + transform.right * Random.Range(-5f, 5f);
				if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
				{
					val = transform.right;
				}
				if (IsProvidenceDodgeBlocked(transform.position, val))
				{
					val *= -1f;
				}
				ApplyProvidenceDodgeImpulse(marker, val);
			}
		}

		private static void PlayManagedPowerDodgeAnimation(GabrielPower marker)
		{
			if ((Object)(object)marker == (Object)null || (Object)(object)((Component)marker).gameObject == (Object)null)
			{
				return;
			}
			Power val = (marker.Power = (((Object)(object)marker.Power != (Object)null) ? marker.Power : ((Component)marker).GetComponent<Power>()));
			if ((Object)(object)val != (Object)null && PowerBackdashMethod != null)
			{
				try
				{
					PowerBackdashMethod.Invoke(val, PowerBackdashAnimationArgs);
					return;
				}
				catch
				{
				}
			}
			Animator val2 = (marker.Animator = (((Object)(object)marker.Animator != (Object)null) ? marker.Animator : ((Component)marker).GetComponent<Animator>()));
			if ((Object)(object)val2 != (Object)null)
			{
				val2.Play("Backdash", 0, 0f);
			}
		}

		private static void ApplyProvidenceDodgeImpulse(GabrielPower marker, Vector3 direction)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)marker == (Object)null) && !((Object)(object)((Component)marker).gameObject == (Object)null) && !(((Vector3)(ref direction)).sqrMagnitude < 0.001f))
			{
				if (IsProvidenceDodgeBlocked(((Component)marker).transform.position, ((Vector3)(ref direction)).normalized))
				{
					direction *= -1f;
				}
				Rigidbody component = ((Component)marker).GetComponent<Rigidbody>();
				if (!((Object)(object)component == (Object)null))
				{
					EnemyIdentifier val = (((Object)(object)marker.EnemyIdentifier != (Object)null) ? marker.EnemyIdentifier : ((Component)marker).GetComponent<EnemyIdentifier>());
					float num = (((Object)(object)val == (Object)null) ? 1f : val.totalSpeedModifier);
					component.AddForce(((Vector3)(ref direction)).normalized * 750f * num, (ForceMode)1);
				}
			}
		}

		private static bool IsProvidenceDodgeBlocked(Vector3 origin, Vector3 direction)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (((Vector3)(ref direction)).sqrMagnitude >= 0.001f)
			{
				return PortalPhysicsV2.Raycast(origin, direction, 7f, LayerMask.op_Implicit(LayerMaskDefaults.Get((LMD)1)), (QueryTriggerInteraction)0);
			}
			return false;
		}

		private static bool ShouldRepeatProvidenceHookDodge(EnemyIdentifier eid)
		{
			try
			{
				return Enemy.InitializeDifficulty(eid) >= 2;
			}
			catch
			{
				return true;
			}
		}

		private static IEnumerator DelayedProvidenceHookDodge(GabrielPower marker)
		{
			yield return (object)new WaitForSeconds(0.1f);
			ApplyProvidenceHookDodge(marker);
		}

		private static void MovePowerInstantly(GameObject go, Vector3 position)
		{
			//IL_0010: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			go.transform.position = position;
			Rigidbody component = go.GetComponent<Rigidbody>();
			if (!((Object)(object)component == (Object)null))
			{
				component.position = position;
				if (!component.isKinematic)
				{
					component.velocity = Vector3.zero;
				}
			}
		}

		private static void UpdateIdlePlayerFollowing()
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			if (!GabrielingsConfig.FollowPlayerWhenIdle)
			{
				return;
			}
			NewMovement instance = MonoSingleton<NewMovement>.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)((Component)instance).transform == (Object)null)
			{
				return;
			}
			for (int i = 0; i < _alivePowers.Count; i++)
			{
				GameObject val = _alivePowers[i];
				if (!((Object)(object)val == (Object)null))
				{
					GabrielPower component = val.GetComponent<GabrielPower>();
					if (!((Object)(object)component == (Object)null) && ShouldFollowPlayer(component, ((Component)instance).transform.position))
					{
						Vector3 followPosition = CalculateFollowPosition(component, ((Component)instance).transform);
						MovePowerTowardFollowPosition(val, followPosition);
					}
				}
			}
		}

		private static bool ShouldFollowPlayer(GabrielPower marker, Vector3 playerPosition)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)marker == (Object)null)
			{
				return false;
			}
			if ((Object)(object)marker.Power != (Object)null && marker.Power.inAction)
			{
				return false;
			}
			if (IsSelectablePowerTarget(marker.CurrentTarget))
			{
				return false;
			}
			Vector3 val = ((Component)marker).transform.position - playerPosition;
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			if (sqrMagnitude > 484f)
			{
				return true;
			}
			return sqrMagnitude > 49f;
		}

		private static Vector3 CalculateFollowPosition(GabrielPower marker, Transform player)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			Vector3 forward = player.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
			{
				forward = Vector3.forward;
			}
			((Vector3)(ref forward)).Normalize();
			Vector3 val = player.right;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
			{
				val = Vector3.Cross(Vector3.up, forward);
			}
			((Vector3)(ref val)).Normalize();
			int num = Mathf.Abs(marker.FollowIndex);
			float num2 = (((num & 1) == 0) ? 1f : (-1f)) * (2.6f + (float)(num % 3) * 0.9f);
			float num3 = 5.5f + (float)(num / 2 % 3) * 1.2f;
			float num4 = 2.2f + (float)(num % 4) * 0.35f + Mathf.Sin(Time.time * 1.8f + marker.FollowPhase) * 0.3f;
			return player.position - forward * num3 + val * num2 + Vector3.up * num4;
		}

		private static void MovePowerTowardFollowPosition(GameObject go, Vector3 followPosition)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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)
			Vector3 val = followPosition - go.transform.position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			if (magnitude < 0.75f)
			{
				return;
			}
			Rigidbody component = go.GetComponent<Rigidbody>();
			if (magnitude > 70f)
			{
				go.transform.position = followPosition;
				if ((Object)(object)component != (Object)null && !component.isKinematic)
				{
					component.velocity = Vector3.zero;
				}
				return;
			}
			float num = Mathf.Lerp(5f, 18f, Mathf.InverseLerp(2f, 30f, magnitude));
			Vector3 val2 = ((Vector3)(ref val)).normalized * num;
			if ((Object)(object)component != (Object)null && !component.isKinematic)
			{
				component.velocity = Vector3.Lerp(component.velocity, val2, Time.deltaTime * 4f);
			}
			else
			{
				go.transform.position = Vector3.MoveTowards(go.transform.position, followPosition, num * Time.deltaTime);
			}
		}

		private static EnemyIdentifier ResolveColliderEnemy(Collider other)
		{
			if ((Object)(object)other == (Object)null)
			{
				return null;
			}
			EnemyIdentifierIdentifier componentInParent = ((Component)other).GetComponentInParent<EnemyIdentifierIdentifier>();
			if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.eid != (Object)null)
			{
				return componentInParent.eid;
			}
			return ((Component)other).GetComponentInParent<EnemyIdentifier>();
		}

		private static void StartClearGrace(string reason)
		{
			_remainingEnemySnapshot = 0;
			if (_clearGraceTimer <= 0f)
			{
				_clearGraceTimer = 1.25f;
				Plugin.LogDebug("No tracked enemies remain after " + reason + "; waiting briefly for a next wave.");
			}
		}

		private static bool WaitForWaveContinuation()
		{
			if (_clearGraceTimer <= 0f)
			{
				_clearGraceTimer = 1.25f;
				return true;
			}
			_clearGraceTimer -= Time.deltaTime;
			return _clearGraceTimer > 0f;
		}

		private static void FinishAssist()
		{
			_clearGraceTimer = 0f;
			DespawnAll();
			_trackedEnemies.Clear();
			_trackedArena = null;
		}

		private static void HandleEnemyAdded(EnemyIdentifier eid)
		{
			if (!((Object)(object)eid == (Object)null))
			{
				if (_alivePowers.Count > 0 || _trackedEnemies.Count > 0)
				{
					AddWaveTarget(eid);
				}
				else if (!((Object)(object)_pendingLockedDoor == (Object)null) || _pendingOpenAreaScan)
				{
					Plugin.LogDebug("Enemy added during pending fallback scan: " + DescribeEnemy(eid) + ".");
					TryStartAssistFromCurrentEnemies("enemy-added fallback");
				}
			}
		}

		private static void AddWaveTarget(EnemyIdentifier eid)
		{
			if (IsValidAssistTarget(eid) && !_trackedEnemies.Contains(eid) && (!_targetByPlayerProximity || IsTargetCloseToPlayer(eid)))
			{
				GameObject gameObject = ((Component)eid).gameObject;
				if (!((Object)(object)gameObject == (Object)null) && gameObject.activeInHierarchy)
				{
					_trackedEnemies.Add(eid);
					_remainingEnemySnapshot = CountRemainingTrackedEnemies();
					_clearGraceTimer = 0f;
					Plugin.LogDebug($"Wave target tracked: {DescribeEnemy(eid)}; {_remainingEnemySnapshot} enemies remain.");
				}
			}
		}

		private static void PruneTrackedTargetsOutsidePlayerRange()
		{
			if (!_targetByPlayerProximity)
			{
				return;
			}
			for (int num = _trackedEnemies.Count - 1; num >= 0; num--)
			{
				EnemyIdentifier val = _trackedEnemies[num];
				if ((Object)(object)val == (Object)null || !IsTargetCloseToPlayer(val))
				{
					ClearManagedPowerTarget(val);
					_trackedEnemies.RemoveAt(num);
				}
			}
		}

		private static void ClearManagedPowerTarget(EnemyIdentifier target)
		{
			for (int i = 0; i < _alivePowers.Count; i++)
			{
				GameObject val = _alivePowers[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				GabrielPower component = val.GetComponent<GabrielPower>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component.CurrentTarget != (Object)(object)target))
				{
					component.CurrentTarget = null;
					if ((Object)(object)component.EnemyIdentifier != (Object)null)
					{
						component.EnemyIdentifier.ResetTarget();
					}
				}
			}
		}

		private static bool IsTargetCloseToPlayer(EnemyIdentifier target)
		{
			//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_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target == (Object)null || !TryGetPlayerPosition(out var position))
			{
				return false;
			}
			Vector3 val = ((Component)target).transform.position - position;
			return ((Vector3)(ref val)).sqrMagnitude <= 3025f;
		}

		private static bool TryGetPlayerPosition(out Vector3 position)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			NewMovement instance = MonoSingleton<NewMovement>.Instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)((Component)instance).transform != (Object)null)
			{
				position = ((Component)instance).transform.position;
				return true;
			}
			position = Vector3.zero;
			return false;
		}

		public static bool IsManagedPower(Power power)
		{
			GabrielPower gabrielPower = default(GabrielPower);
			if ((Object)(object)power != (Object)null)
			{
				return ((Component)power).TryGetComponent<GabrielPower>(ref gabrielPower);
			}
			return false;
		}

		public static void DetachFromPowerCooldowns(Power power)
		{
			if (!IsManagedPower(power))
			{
				return;
			}
			EnemyCooldowns instance = MonoSingleton<EnemyCooldowns>.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				instance.RemovePower(power);
				if ((Object)(object)instance.attackingPower == (Object)(object)power)
				{
					instance.attackingPower = null;
				}
			}
		}

		private static void OnCheckpointRestart()
		{
			HandleCheckpointRestart("StatsManager.checkpointRestart");
		}
	}
}
namespace Gabrielings.Patches
{
	public struct PowerCooldownState
	{
		public bool Applied;

		public EnemyCooldowns Cooldowns;

		public Power PreviousAttackingPower;
	}
	[HarmonyPatch]
	public static class AllPatches
	{
	}
	[HarmonyPatch(typeof(ActivateArena), "Activate", new Type[] { })]
	public static class ActivateArena_Activate_Patch
	{
		[HarmonyPrefix]
		public static void Prefix(ActivateArena __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				PowerSpawnManager.HandleArenaActivated(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Door), "Lock", new Type[] { })]
	public static class Door_Lock_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(Door __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				PowerSpawnManager.HandleDoorLocked(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(BossHealthBar), "OnEnable", new Type[] { })]
	public static class BossHealthBar_OnEnable_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(BossHealthBar __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				PowerSpawnManager.HandleBossHealthBar(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Power), "Update", new Type[] { })]
	public static class Power_Update_Patch
	{
		[HarmonyPrefix]
		public static void Prefix(Power __instance, ref PowerCooldownState __state)
		{
			if (PowerSpawnManager.IsManagedPower(__instance))
			{
				EnemyCooldowns instance = MonoSingleton<EnemyCooldowns>.Instance;
				if (!((Object)(object)instance == (Object)null) && instance.powers != null)
				{
					__state.Applied = true;
					__state.Cooldowns = instance;
					__state.PreviousAttackingPower = instance.attackingPower;
					instance.attackingPower = null;
					instance.powers.Remove(__instance);
					instance.powers.Insert(0, __instance);
				}
			}
		}

		[HarmonyFinalizer]
		public static Exception Finalizer(Exception __exception, Power __instance, PowerCooldownState __state)
		{
			if (__state.Applied && (Object)(object)__state.Cooldowns != (Object)null)
			{
				__state.Cooldowns.powers.Remove(__instance);
				__state.Cooldowns.attackingPower = __state.PreviousAttackingPower;
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(EnemyCooldowns), "AddPower", new Type[] { typeof(Power) })]
	public static class EnemyCooldowns_AddPower_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(Power pwr)
		{
			PowerSpawnManager.DetachFromPowerCooldowns(pwr);
		}
	}
	[HarmonyPatch(typeof(Power), "StopAction", new Type[] { })]
	public static class Power_StopAction_Patch
	{
		[HarmonyPrefix]
		public static void Prefix(Power __instance, ref PowerCooldownState __state)
		{
			PowerPatchSupport.PrepareManagedAttackEnd(__instance, ref __state);
		}

		[HarmonyFinalizer]
		public static Exception Finalizer(Exception __exception, Power __instance, PowerCooldownState __state)
		{
			PowerPatchSupport.RestoreManagedAttackEnd(__instance, __state);
			return __exception;
		}
	}
	[HarmonyPatch(typeof(Power), "PlaySound", new Type[]
	{
		typeof(AudioClip),
		typeof(bool),
		typeof(bool),
		typeof(float)
	})]
	public static class Power_PlaySound_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(Power __instance)
		{
			return !PowerSpawnManager.ShouldMuteManagedPowerVoice(__instance);
		}
	}
	[HarmonyPatch(typeof(Power), "CanPlaySound", new Type[] { typeof(bool) })]
	public static class Power_CanPlaySound_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(Power __instance, ref bool __result)
		{
			if (!PowerSpawnManager.ShouldMuteManagedPowerVoice(__instance))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
	[HarmonyPatch(typeof(Power), "DespawnWeapon", new Type[]
	{
		typeof(GameObject),
		typeof(bool)
	})]
	public static class Power_DespawnWeapon_Patch
	{
		[HarmonyPrefix]
		public static void Prefix(Power __instance, ref PowerCooldownState __state)
		{
			PowerPatchSupport.PrepareManagedAttackEnd(__instance, ref __state);
		}

		[HarmonyFinalizer]
		public static Exception Finalizer(Exception __exception, Power __instance, PowerCooldownState __state)
		{
			PowerPatchSupport.RestoreManagedAttackEnd(__instance, __state);
			return __exception;
		}
	}
	public static class PowerPatchSupport
	{
		public static void PrepareManagedAttackEnd(Power power, ref PowerCooldownState state)
		{
			if (PowerSpawnManager.IsManagedPower(power))
			{
				EnemyCooldowns instance = MonoSingleton<EnemyCooldowns>.Instance;
				if (!((Object)(object)instance == (Object)null))
				{
					state.Applied = true;
					state.Cooldowns = instance;
					state.PreviousAttackingPower = (((Object)(object)instance.attackingPower == (Object)(object)power) ? null : instance.attackingPower);
					instance.attackingPower = power;
				}
			}
		}

		public static void RestoreManagedAttackEnd(Power power, PowerCooldownState state)
		{
			if (state.Applied && !((Object)(object)state.Cooldowns == (Object)null))
			{
				PowerSpawnManager.DetachFromPowerCooldowns(power);
				if ((Object)(object)state.Cooldowns.attackingPower == (Object)null || (Object)(object)state.Cooldowns.attackingPower == (Object)(object)power)
				{
					state.Cooldowns.attackingPower = state.PreviousAttackingPower;
				}
			}
		}
	}
	[HarmonyPatch(typeof(EnemyCooldowns), "PowerAttackEnd", new Type[] { })]
	public static class EnemyCooldowns_PowerAttackEnd_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(Power __state)
		{
			PowerSpawnManager.DetachFromPowerCooldowns(__state);
		}

		[HarmonyPrefix]
		public static void Prefix(EnemyCooldowns __instance, ref Power __state)
		{
			__state = (((Object)(object)__instance == (Object)null) ? null : __instance.attackingPower);
		}
	}
	[HarmonyPatch(typeof(EnemyIdentifier), "UpdateTarget", new Type[] { })]
	public static class EnemyIdentifier_UpdateTarget_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(EnemyIdentifier __instance)
		{
			PowerSpawnManager.HandleEnemyTargetUpdated(__instance);
		}
	}
	[HarmonyPatch(typeof(Projectile), "Start", new Type[] { })]
	public static class Projectile_Start_Patch
	{
		[HarmonyPrefix]
		public static void Prefix(Projectile __instance)
		{
			PowerSpawnManager.ConfigureManagedPowerProjectile(__instance);
		}

		[HarmonyPostfix]
		public static void Postfix(Projectile __instance)
		{
			PowerSpawnManager.ConfigureManagedPowerProjectile(__instance);
		}
	}
	[HarmonyPatch(typeof(Projectile), "OnTriggerEnter", new Type[] { typeof(Collider) })]
	public static class Projectile_OnTriggerEnter_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(Projectile __instance, Collider other)
		{
			if (PowerSpawnManager.ShouldSkipManagedPowerProjectileCollision(__instance, other))
			{
				return false;
			}
			PowerSpawnManager.MarkEnemyProjectileDamageToManagedPower(__instance, other);
			PowerSpawnManager.PrepareManagedPowerProjectileHit(__instance, other);
			return true;
		}
	}
	[HarmonyPatch(typeof(Explosion), "OnTriggerEnter", new Type[] { typeof(Collider) })]
	public static class Explosion_OnTriggerEnter_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(Explosion __instance, Collider other)
		{
			return !PowerSpawnManager.ShouldSkipManagedPowerExplosionCollision(__instance, other);
		}
	}
	[HarmonyPatch(typeof(SwingCheck2), "CheckEidCollision", new Type[]
	{
		typeof(EnemyIdentifier),
		typeof(Collider)
	})]
	public static class SwingCheck2_CheckEidCollision_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(SwingCheck2 __instance, EnemyIdentifier enid, Collider other, EnemyIdentifier ___eid)
		{
			if (PowerSpawnManager.ShouldSkipManagedPowerMeleeEnemyCollision(__instance, enid))
			{
				return false;
			}
			if (PowerSpawnManager.TryHandleManagedPowerFleshBossMeleeCollision(__instance, enid, other, ___eid))
			{
				return false;
			}
			PowerSpawnManager.MarkEnemyMeleeDamageToManagedPower(enid, ___eid);
			return true;
		}
	}
	[HarmonyPatch(typeof(SwingCheck2), "DamageStart", new Type[] { })]
	public static class SwingCheck2_DamageStart_Patch
	{
		[HarmonyPrefix]
		public static void Prefix(SwingCheck2 __instance)
		{
			PowerSpawnManager.ClearManagedPowerMeleeHitRecord(__instance);
		}
	}
	[HarmonyPatch(typeof(SwingCheck2), "DamageStop", new Type[] { })]
	public static class SwingCheck2_DamageStop_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(SwingCheck2 __instance)
		{
			PowerSpawnManager.ClearManagedPowerMeleeHitRecord(__instance);
		}
	}
	[HarmonyPatch(typeof(SwingCheck2), "CheckCollision", new Type[] { typeof(Collider) })]
	public static class SwingCheck2_CheckCollision_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(SwingCheck2 __instance, Collider other)
		{
			return !PowerSpawnManager.ShouldSkipManagedPowerMeleeCollision(__instance, other);
		}
	}
	[HarmonyPatch(typeof(HookArm), "FixedUpdate", new Type[] { })]
	public static class HookArm_FixedUpdate_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(HookArm __instance, EnemyIdentifier ___caughtEid)
		{
			PowerSpawnManager.HandleManagedPowerHooked(__instance, ___caughtEid);
		}
	}
	[HarmonyPatch(typeof(Punch), "ParryProjectile", new Type[] { typeof(Projectile) })]
	public static class Punch_ParryProjectile_Patch
	{
		[HarmonyPrefix]
		public static void Prefix(Projectile proj, ref bool __state)
		{
			__state = PowerSpawnManager.BeginManagedPowerProjectileParry(proj);
		}

		[HarmonyFinalizer]
		public static Exception Finalizer(Exception __exception, bool __state)
		{
			if (__state)
			{
				PowerSpawnManager.EndManagedPowerProjectileParry();
			}
			return __exception;
		}
	}
	[HarmonyPatch(typeof(NewMovement), "GetHealth", new Type[]
	{
		typeof(int),
		typeof(bool),
		typeof(bool),
		typeof(bool)
	})]
	public static class NewMovement_GetHealth_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(int health, bool silent)
		{
			return !PowerSpawnManager.ShouldSuppressManagedPowerProjectileParryHealing(health, silent);
		}
	}
	[HarmonyPatch(typeof(StatsManager), "Restart", new Type[] { })]
	public static class StatsManager_Restart_Patch
	{
		[HarmonyPrefix]
		public static void Prefix()
		{
			PowerSpawnManager.HandleCheckpointRestart("StatsManager.Restart");
		}
	}
	[HarmonyPatch(typeof(CheckPoint), "ActivateCheckPoint", new Type[] { })]
	public static class CheckPoint_ActivateCheckPoint_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(CheckPoint __instance)
		{
			PowerSpawnManager.HandleCheckpointActivated(__instance);
		}
	}
	[HarmonyPatch(typeof(CheckPoint), "OnRespawn", new Type[] { })]
	public static class CheckPoint_OnRespawn_Patch
	{
		[HarmonyPrefix]
		public static void Prefix(CheckPoint __instance)
		{
			PowerSpawnManager.HandleCheckpointRestart("CheckPoint.OnRespawn");
		}
	}
	[HarmonyPatch(typeof(NewMovement), "GetHurt", new Type[]
	{
		typeof(int),
		typeof(bool),
		typeof(float),
		typeof(bool),
		typeof(bool),
		typeof(float),
		typeof(bool)
	})]
	public static class NewMovement_GetHurt_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(NewMovement __instance)
		{
			if ((Object)(object)__instance != (Object)null && __instance.dead)
			{
				PowerSpawnManager.HandlePlayerDeath();
			}
		}
	}
	[HarmonyPatch(typeof(Enemy), "OnTravel", new Type[] { typeof(PortalTravelDetails) })]
	public static class Enemy_OnTravel_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(Enemy __instance, ref bool? __result)
		{
			if (!PowerSpawnManager.ShouldBlockManagedPowerPortalTravel(__instance))
			{
				return true;
			}
			__result = null;
			return false;
		}
	}
	[HarmonyPatch(typeof(Enemy), "OnTeleportBlocked", new Type[] { typeof(PortalTravelDetails) })]
	public static class Enemy_OnTeleportBlocked_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(Enemy __instance)
		{
			return !PowerSpawnManager.ShouldBlockManagedPowerPortalTravel(__instance);
		}
	}
	[HarmonyPatch(typeof(EnemyIdentifier), "DeliverDamage", new Type[]
	{
		typeof(GameObject),
		typeof(Vector3),
		typeof(Vector3),
		typeof(float),
		typeof(bool),
		typeof(float),
		typeof(GameObject),
		typeof(bool),
		typeof(bool)
	})]
	public static class EnemyIdentifier_DeliverDamage_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(EnemyIdentifier __instance, GameObject target, GameObject sourceWeapon)
		{
			return !PowerSpawnManager.ShouldBlockManagedPowerDamage(__instance, target, sourceWeapon);
		}
	}
	[HarmonyPatch(typeof(EnemyIdentifier), "ProcessDeath", new Type[] { typeof(bool) })]
	public static class EnemyIdentifier_ProcessDeath_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(EnemyIdentifier __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && __instance.dead && EnemyFilter.IsArenaTarget(__instance))
			{
				PowerSpawnManager.NotifyPowerKilledEnemy(__instance);
			}
		}
	}
}
namespace Gabrielings.Conf